// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/test/scenes/spinning_sprites_scene.h"

#include <cmath>
#include <vector>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/math/point_f.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/render_tree/image_node.h"
#include "cobalt/render_tree/matrix_transform_node.h"
#include "cobalt/renderer/test/png_utils/png_decode.h"

using cobalt::math::Matrix3F;
using cobalt::math::PointF;
using cobalt::math::RectF;
using cobalt::math::RotateMatrix;
using cobalt::math::ScaleMatrix;
using cobalt::math::SizeF;
using cobalt::math::TranslateMatrix;
using cobalt::render_tree::animations::AnimateNode;
using cobalt::render_tree::animations::Animation;
using cobalt::render_tree::animations::AnimationList;
using cobalt::render_tree::CompositionNode;
using cobalt::render_tree::Image;
using cobalt::render_tree::ImageNode;
using cobalt::render_tree::MatrixTransformNode;
using cobalt::render_tree::Node;
using cobalt::render_tree::ResourceProvider;
using cobalt::renderer::test::png_utils::DecodePNGToRenderTreeImage;

namespace cobalt {
namespace renderer {
namespace test {
namespace scenes {

namespace {

struct SpriteInfo {
  float scale;
  float rotation_speed;  // In revolutions per second.
  PointF position;       // In normalized device coordinates.
};

float RandRange(float lower, float upper) {
  return base::RandDouble() * (upper - lower) + lower;
}

void AnimateSprite(base::TimeDelta start_time, const SpriteInfo& sprite_info,
                   const RectF& child_rect,
                   MatrixTransformNode::Builder* transform_node,
                   base::TimeDelta time) {
  // Setup child node's scale and rotation and translation.
  float theta =
      (time - start_time).InSecondsF() * sprite_info.rotation_speed * 2 * M_PI;
  transform_node->transform =
      transform_node->transform * RotateMatrix(theta) *
      ScaleMatrix(sprite_info.scale) *
      TranslateMatrix(  // Set child center as origin.
          -0.5 * child_rect.width(), -0.5 * child_rect.height());
}

std::vector<SpriteInfo> CreateSpriteInfos() {
  // Create a set of randomly positioned and sized sprites.
  std::vector<SpriteInfo> sprite_infos;
  const int kNumSprites = 40;
  for (int i = 0; i < kNumSprites; ++i) {
    const float kMinScale = 0.1f;
    const float kMaxScale = 0.7f;
    SpriteInfo sprite_info;
    sprite_info.scale = RandRange(kMinScale, kMaxScale);

    sprite_info.position.set_x(static_cast<float>(base::RandDouble()));
    sprite_info.position.set_y(static_cast<float>(base::RandDouble()));

    const float kMinRotationSpeed = 0.01f;
    const float kMaxRotationSpeed = 0.3f;
    sprite_info.rotation_speed =
        RandRange(kMinRotationSpeed, kMaxRotationSpeed);

    sprite_infos.push_back(sprite_info);
  }
  return sprite_infos;
}

scoped_refptr<Image> GetTestImage(ResourceProvider* resource_provider) {
  // Load a test image from disk.
  base::FilePath data_directory;
  CHECK(base::PathService::Get(base::DIR_TEST_DATA, &data_directory));
  return DecodePNGToRenderTreeImage(
      data_directory.Append(FILE_PATH_LITERAL("test"))
          .Append(FILE_PATH_LITERAL("scenes"))
          .Append(FILE_PATH_LITERAL("demo_image.png")),
      resource_provider);
}

}  // namespace

scoped_refptr<render_tree::Node> CreateSpinningSpritesScene(
    ResourceProvider* resource_provider, const math::SizeF& output_dimensions,
    base::TimeDelta start_time) {
  // Create an image for each SpriteInfo we have in our sprite_infos vector.
  // They will be positioned and scaled according to their SpriteInfo settings,
  // and rotated according to time.
  CompositionNode::Builder spinning_sprites_scene_builder;
  AnimateNode::Builder animations;

  // Now, setup a plurality of spinning images that contain the test image.
  std::vector<SpriteInfo> sprite_infos = CreateSpriteInfos();
  scoped_refptr<Image> test_image = GetTestImage(resource_provider);
  AnimationList<CompositionNode>::Builder sprite_animation_list;
  for (int i = 0; i < sprite_infos.size(); ++i) {
    const SpriteInfo& sprite_info = sprite_infos[i];

    // Create the child image node that references the image data
    scoped_refptr<ImageNode> image_node(new ImageNode(test_image));

    scoped_refptr<MatrixTransformNode> transformed_node(new MatrixTransformNode(
        image_node,
        TranslateMatrix(  // Place the image within the scene.
            sprite_info.position.x() * output_dimensions.width(),
            sprite_info.position.y() * output_dimensions.height())));

    // Add the child image node to the list of composed nodes.
    spinning_sprites_scene_builder.AddChild(transformed_node);

    animations.Add(transformed_node,
                   base::Bind(&AnimateSprite, start_time, sprite_info,
                              image_node->data().destination_rect));
  }

  scoped_refptr<CompositionNode> spinning_sprites_composition(
      new CompositionNode(std::move(spinning_sprites_scene_builder)));

  return new AnimateNode(animations, spinning_sprites_composition);
}

}  // namespace scenes
}  // namespace test
}  // namespace renderer
}  // namespace cobalt
