/*
 * Copyright 2016 Google Inc. 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 <string>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/math/size_f.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/render_tree/animations/animate_node.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/font.h"
#include "cobalt/render_tree/glyph_buffer.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/render_tree/image_node.h"
#include "cobalt/render_tree/matrix_transform_node.h"
#include "cobalt/render_tree/node_visitor.h"
#include "cobalt/render_tree/rect_node.h"
#include "cobalt/render_tree/text_node.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace render_tree {
namespace animations {

using ::cobalt::math::SizeF;
using ::cobalt::math::RectF;

// Helper function to create an animation set for a render tree that consists
// of only one animation targeting only one node in the render tree.
template <typename T>
scoped_refptr<AnimateNode> CreateSingleAnimation(
    const scoped_refptr<T>& target,
    typename Animation<T>::Function anim_function) {
  AnimateNode::Builder animations_builder;
  animations_builder.Add(target, anim_function);
  return new AnimateNode(animations_builder, target);
}

class ImageFake : public Image {
 public:
  const math::Size& GetSize() const OVERRIDE { return size_; }

 private:
  math::Size size_;
};

// The following tests ensure that simple single time-independent animations
// work fine on single-node render trees of different types.
void AnimateText(TextNode::Builder* text_node, base::TimeDelta time_elapsed) {
  UNREFERENCED_PARAMETER(time_elapsed);
  text_node->color = ColorRGBA(.5f, .5f, .5f);
}
TEST(AnimateNodeTest, EnsureSingleTextNodeAnimates) {
  scoped_refptr<TextNode> text_node(
      new TextNode(math::Vector2dF(0, 0), new GlyphBuffer(RectF(0, 0, 1, 1)),
                   ColorRGBA(1.0f, 1.0f, 1.0f)));

  scoped_refptr<AnimateNode> with_animations =
      CreateSingleAnimation(text_node, base::Bind(&AnimateText));

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));
  TextNode* animated_text_node =
      dynamic_cast<TextNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_text_node);
  EXPECT_EQ(ColorRGBA(.5f, .5f, .5f), animated_text_node->data().color);
}

void AnimateImage(ImageNode::Builder* image_node,
                  base::TimeDelta time_elapsed) {
  UNREFERENCED_PARAMETER(time_elapsed);
  image_node->destination_rect = RectF(2.0f, 2.0f);
}
TEST(AnimateNodeTest, EnsureSingleImageNodeAnimates) {
  scoped_refptr<ImageNode> image_node(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));

  scoped_refptr<AnimateNode> with_animations =
      CreateSingleAnimation(image_node, base::Bind(&AnimateImage));

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));
  ImageNode* animated_image_node =
      dynamic_cast<ImageNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_image_node);
  EXPECT_TRUE(animated_image_node);
  EXPECT_EQ(RectF(2.0f, 2.0f), animated_image_node->data().destination_rect);
}

void AnimateRect(RectNode::Builder* rect_node, base::TimeDelta time_elapsed) {
  UNREFERENCED_PARAMETER(time_elapsed);
  rect_node->rect = RectF(2.0f, 2.0f);
}
TEST(AnimateNodeTest, EnsureSingleRectNodeAnimates) {
  scoped_refptr<RectNode> rect_node(new RectNode(
      RectF(1.0f, 1.0f),
      scoped_ptr<Brush>(new SolidColorBrush(ColorRGBA(1.0f, 1.0f, 1.0f)))));

  scoped_refptr<AnimateNode> with_animations =
      CreateSingleAnimation(rect_node, base::Bind(&AnimateRect));

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));
  RectNode* animated_rect_node =
      dynamic_cast<RectNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_rect_node);
  EXPECT_TRUE(animated_rect_node);
  EXPECT_EQ(RectF(2.0f, 2.0f), animated_rect_node->data().rect);
}

// Test that time is being passed through correctly and that we can animate
// the same tree repeatedly with different time values to produce different
// results.
void AnimateImageAddWithTime(ImageNode::Builder* image_node,
                             base::TimeDelta time_elapsed) {
  image_node->destination_rect.Outset(
      static_cast<float>(time_elapsed.InSecondsF()),
      static_cast<float>(time_elapsed.InSecondsF()));
}
TEST(AnimateNodeTest, SingleImageNodeAnimatesOverTimeRepeatedlyCorrectly) {
  scoped_refptr<ImageNode> image_node(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));

  scoped_refptr<AnimateNode> with_animations =
      CreateSingleAnimation(image_node, base::Bind(&AnimateImageAddWithTime));

  scoped_refptr<Node> animated_render_tree;
  ImageNode* animated_image_node;

  animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));
  animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_image_node);
  EXPECT_TRUE(animated_image_node);
  EXPECT_FLOAT_EQ(3.0f, animated_image_node->data().destination_rect.width());

  animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(2));
  animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_image_node);
  EXPECT_TRUE(animated_image_node);
  EXPECT_FLOAT_EQ(5.0f, animated_image_node->data().destination_rect.width());

  animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(4));
  animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_image_node);
  EXPECT_TRUE(animated_image_node);
  EXPECT_FLOAT_EQ(9.0f, animated_image_node->data().destination_rect.width());
}

// Test that nodes with multiple animations targeting them work correctly, and
// that the animations are applied in the correct order.
void AnimateImageScaleWithTime(ImageNode::Builder* image_node,
                               base::TimeDelta time_elapsed) {
  math::SizeF image_size = image_node->destination_rect.size();
  image_size.Scale(static_cast<float>(time_elapsed.InSecondsF()),
                   static_cast<float>(time_elapsed.InSecondsF()));
  image_node->destination_rect.set_size(image_size);
}
TEST(AnimateNodeTest, MultipleAnimationsTargetingOneNodeApplyInCorrectOrder) {
  scoped_refptr<ImageNode> image_node(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));

  // Here we add 2 animations both targeting the same ImageNode.  We expect
  // them to be applied in the order that they appear in the list.  We test this
  // by issuing both an add and then a multiply to the image node's destination
  // size property, so that the result depends on the order of operations.
  AnimationList<ImageNode>::Builder animation_list_builder;
  animation_list_builder.animations.push_back(
      base::Bind(&AnimateImageAddWithTime));
  animation_list_builder.animations.push_back(
      base::Bind(&AnimateImageScaleWithTime));

  AnimateNode::Builder animations_builder;
  animations_builder.Add(image_node,
                         make_scoped_refptr(new AnimationList<ImageNode>(
                             animation_list_builder.Pass())));
  scoped_refptr<AnimateNode> with_animations(
      new AnimateNode(animations_builder, image_node));

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(3));

  ImageNode* animated_image_node =
      dynamic_cast<ImageNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_image_node);

  EXPECT_FLOAT_EQ(21.0f, animated_image_node->data().destination_rect.width());
}

// Test that animating a transform node correctly adjusts parameters but
// leaves its child node untouched.
void AnimateTransform(MatrixTransformNode::Builder* transform_node,
                      base::TimeDelta time_elapsed) {
  UNREFERENCED_PARAMETER(time_elapsed);
  transform_node->transform = math::TranslateMatrix(2.0f, 2.0f);
}
TEST(AnimateNodeTest, AnimatingTransformNodeDoesNotAffectSourceChild) {
  scoped_refptr<ImageNode> image_node(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));
  scoped_refptr<MatrixTransformNode> transform_node(
      new MatrixTransformNode(image_node, math::Matrix3F::Identity()));

  scoped_refptr<AnimateNode> with_animations =
      CreateSingleAnimation(transform_node, base::Bind(&AnimateTransform));

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));

  MatrixTransformNode* animated_transform_node =
      dynamic_cast<MatrixTransformNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_transform_node);

  EXPECT_EQ(math::TranslateMatrix(2.0f, 2.0f),
            animated_transform_node->data().transform);
  EXPECT_EQ(image_node.get(), animated_transform_node->data().source.get());
}

// Test that animating a child correctly adjusts sub-node parameters but
// not parent node parameters, though both child and parent are different nodes
// now.  The animated child's sibling should be left untouched.
TEST(AnimateNodeTest,
     AnimatingCompositionChildNodeAffectsParentAsWellButNotSibling) {
  scoped_refptr<ImageNode> image_node_a(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));
  scoped_refptr<ImageNode> image_node_b(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));
  CompositionNode::Builder composition_node_builder;
  composition_node_builder.AddChild(image_node_a);
  composition_node_builder.AddChild(image_node_b);
  scoped_refptr<CompositionNode> composition_node(
      new CompositionNode(composition_node_builder.Pass()));

  AnimateNode::Builder animation_builder;
  animation_builder.Add(image_node_a, base::Bind(&AnimateImage));
  scoped_refptr<AnimateNode> with_animations =
      new AnimateNode(animation_builder, composition_node);

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));

  CompositionNode* animated_composition_node =
      dynamic_cast<CompositionNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_composition_node);

  ImageNode* animated_image_node_a = dynamic_cast<ImageNode*>(
      animated_composition_node->data().children()[0].get());
  EXPECT_TRUE(animated_image_node_a);
  EXPECT_EQ(RectF(2.0f, 2.0f), animated_image_node_a->data().destination_rect);

  ImageNode* animated_image_node_b = dynamic_cast<ImageNode*>(
      animated_composition_node->data().children()[1].get());
  EXPECT_EQ(image_node_b.get(), animated_image_node_b);
}

TEST(AnimateNodeTest, SimpleSubAnimateNode) {
  // Test that we can properly animate trees that built upon multiple
  // AnimateNodes.
  scoped_refptr<ImageNode> image_node(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));
  scoped_refptr<AnimateNode> image_animation =
      CreateSingleAnimation(image_node, base::Bind(&AnimateImage));

  scoped_refptr<MatrixTransformNode> transform_node(
      new MatrixTransformNode(image_animation, math::Matrix3F::Identity()));

  scoped_refptr<AnimateNode> with_animations =
      CreateSingleAnimation(transform_node, base::Bind(&AnimateTransform));

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));

  MatrixTransformNode* animated_transform_node =
      dynamic_cast<MatrixTransformNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_transform_node);

  // Check that the matrix transform node is animated.
  EXPECT_EQ(math::TranslateMatrix(2.0f, 2.0f),
            animated_transform_node->data().transform);

  // Check also that the image node is animated.
  ImageNode* animated_image_node =
      dynamic_cast<ImageNode*>(animated_transform_node->data().source.get());
  EXPECT_TRUE(animated_image_node);
  EXPECT_EQ(RectF(2.0f, 2.0f), animated_image_node->data().destination_rect);
}

TEST(AnimateNodeTest, SubAnimateNodeWithTwoAncestors) {
  // Test that we can properly animate trees that built upon multiple
  // AnimateNodes.
  scoped_refptr<ImageNode> image_node(
      new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f)));
  scoped_refptr<AnimateNode> image_animation =
      CreateSingleAnimation(image_node, base::Bind(&AnimateImage));

  // This node is used to make it so there is more than one node on the path
  // between the two AnimateNodes.
  scoped_refptr<MatrixTransformNode> transform_node_a(
      new MatrixTransformNode(image_animation, math::Matrix3F::Identity()));

  scoped_refptr<MatrixTransformNode> transform_node_b(
      new MatrixTransformNode(transform_node_a, math::Matrix3F::Identity()));

  scoped_refptr<AnimateNode> with_animations =
      new AnimateNode(transform_node_b);

  scoped_refptr<Node> animated_render_tree =
      with_animations->Apply(base::TimeDelta::FromSeconds(1));

  MatrixTransformNode* animated_transform_node =
      dynamic_cast<MatrixTransformNode*>(animated_render_tree.get());
  EXPECT_TRUE(animated_transform_node);

  // Check that the image node is animated.
  MatrixTransformNode* animated_dummy_transform_node =
      dynamic_cast<MatrixTransformNode*>(
          animated_transform_node->data().source.get());
  EXPECT_TRUE(animated_dummy_transform_node);

  ImageNode* animated_image_node = dynamic_cast<ImageNode*>(
      animated_dummy_transform_node->data().source.get());
  EXPECT_TRUE(animated_image_node);
  EXPECT_EQ(RectF(2.0f, 2.0f), animated_image_node->data().destination_rect);
}

}  // namespace animations
}  // namespace render_tree
}  // namespace cobalt
