/*
 * Copyright 2015 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 <cmath>

#include "base/time.h"
#include "cobalt/cssom/calc_value.h"
#include "cobalt/cssom/css_transition.h"
#include "cobalt/cssom/interpolate_property_value.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/length_value.h"
#include "cobalt/cssom/matrix_function.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/cssom/property_definitions.h"
#include "cobalt/cssom/rgba_color_value.h"
#include "cobalt/cssom/rotate_function.h"
#include "cobalt/cssom/scale_function.h"
#include "cobalt/cssom/transform_function_list_value.h"
#include "cobalt/cssom/transform_matrix_function_value.h"
#include "cobalt/cssom/translate_function.h"
#include "cobalt/math/transform_2d.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace cssom {

namespace {
const float kErrorEpsilon = 0.00015f;

// Helper function to animate a propertyby a given progress between a given
// start and end point.  The aniamted value is returned, casted to the passed in
// template type parameter.
template <typename T>
scoped_refptr<T> InterpolatePropertyTyped(
    float progress, const scoped_refptr<PropertyValue>& start,
    const scoped_refptr<PropertyValue>& end) {
  scoped_refptr<PropertyValue> interpolated =
      InterpolatePropertyValue(progress, start, end);

  scoped_refptr<T> interpolated_with_type =
      dynamic_cast<T*>(interpolated.get());
  DCHECK(interpolated_with_type);

  return interpolated_with_type;
}
}  // namespace

TEST(InterpolatePropertyValueTest, NumberValuesInterpolate) {
  scoped_refptr<NumberValue> interpolated =
      InterpolatePropertyTyped<NumberValue>(0.5f, new NumberValue(0.0f),
                                            new NumberValue(1.0f));

  EXPECT_NEAR(interpolated->value(), 0.5f, kErrorEpsilon);
}

TEST(InterpolatePropertyValueTest, RGBAColorValuesInterpolate) {
  scoped_refptr<RGBAColorValue> interpolated =
      InterpolatePropertyTyped<RGBAColorValue>(
          0.25, new RGBAColorValue(0, 100, 0, 100),
          new RGBAColorValue(100, 0, 100, 0));

  EXPECT_EQ(25, interpolated->r());
  EXPECT_EQ(75, interpolated->g());
  EXPECT_EQ(25, interpolated->b());
  EXPECT_EQ(75, interpolated->a());
}

TEST(InterpolatePropertyValueTest, TransformFromNoneToNoneValuesInterpolate) {
  scoped_refptr<KeywordValue> interpolated =
      InterpolatePropertyTyped<KeywordValue>(0.5f, KeywordValue::GetNone(),
                                             KeywordValue::GetNone());

  EXPECT_EQ(KeywordValue::kNone, interpolated->value());
}

TEST(InterpolatePropertyValueTest, TransformSingleRotateValuesInterpolate) {
  struct MakeSingleRotateTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new RotateFunction(1.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new RotateFunction(2.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleRotateTransform::Start(),
          MakeSingleRotateTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const RotateFunction* single_function =
      dynamic_cast<const RotateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_NEAR(single_function->clockwise_angle_in_radians(), 1.5f,
              kErrorEpsilon);
}

TEST(InterpolatePropertyValueTest, TransformSingleScaleValuesInterpolate) {
  struct MakeSingleScaleTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new ScaleFunction(1.0f, 2.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new ScaleFunction(3.0f, 4.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleScaleTransform::Start(),
          MakeSingleScaleTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const ScaleFunction* single_function =
      dynamic_cast<const ScaleFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_NEAR(single_function->x_factor(), 2.0f, kErrorEpsilon);
  EXPECT_NEAR(single_function->y_factor(), 3.0f, kErrorEpsilon);
}

TEST(InterpolatePropertyValueTest, TransformFromNoneToScaleValuesInterpolate) {
  struct MakeSingleScaleTransform {
    static scoped_refptr<PropertyValue> Start() {
      return KeywordValue::GetNone();
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new ScaleFunction(5.0f, 9.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.25f, MakeSingleScaleTransform::Start(),
          MakeSingleScaleTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const ScaleFunction* single_function =
      dynamic_cast<const ScaleFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_NEAR(single_function->x_factor(), 2.0f, kErrorEpsilon);
  EXPECT_NEAR(single_function->y_factor(), 3.0f, kErrorEpsilon);
}

TEST(InterpolatePropertyValueTest, TransformFromScaleToNoneValuesInterpolate) {
  struct MakeSingleScaleTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new ScaleFunction(5.0f, 9.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      return KeywordValue::GetNone();
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.25f, MakeSingleScaleTransform::Start(),
          MakeSingleScaleTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const ScaleFunction* single_function =
      dynamic_cast<const ScaleFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_NEAR(single_function->x_factor(), 4.0f, kErrorEpsilon);
  EXPECT_NEAR(single_function->y_factor(), 7.0f, kErrorEpsilon);
}

void TestTransformSingleTranslateValuesAnimate(TranslateFunction::Axis axis) {
  struct MakeSingleTranslateTransform {
    static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new TranslateFunction(axis, new LengthValue(1.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new TranslateFunction(axis, new LengthValue(2.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleTranslateTransform::Start(axis),
          MakeSingleTranslateTransform::End(axis));

  ASSERT_EQ(1, interpolated->value().size());
  const TranslateFunction* single_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_NEAR(single_function->offset_as_length()->value(), 1.5f,
              kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit, single_function->offset_as_length()->unit());
  EXPECT_EQ(axis, single_function->axis());
}

TEST(InterpolatePropertyValueTest, TransformSingleTranslateXValuesInterpolate) {
  TestTransformSingleTranslateValuesAnimate(TranslateFunction::kXAxis);
}
TEST(InterpolatePropertyValueTest, TransformSingleTranslateYValuesInterpolate) {
  TestTransformSingleTranslateValuesAnimate(TranslateFunction::kYAxis);
}
TEST(InterpolatePropertyValueTest, TransformSingleTranslateZValuesInterpolate) {
  TestTransformSingleTranslateValuesAnimate(TranslateFunction::kZAxis);
}

void TestTransformTranslateFromLengthToPercentageValuesAnimate(
    TranslateFunction::Axis axis) {
  struct MakeSingleTranslateTransform {
    static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new TranslateFunction(axis, new LengthValue(1.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new TranslateFunction(axis, new PercentageValue(0.5f)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleTranslateTransform::Start(axis),
          MakeSingleTranslateTransform::End(axis));

  ASSERT_EQ(1, interpolated->value().size());
  const TranslateFunction* single_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  ASSERT_EQ(TranslateFunction::kCalc, single_function->offset_type());
  EXPECT_NEAR(0.5f, single_function->offset_as_calc()->length_value()->value(),
              kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit,
            single_function->offset_as_calc()->length_value()->unit());
  EXPECT_NEAR(0.25f,
              single_function->offset_as_calc()->percentage_value()->value(),
              kErrorEpsilon);
  EXPECT_EQ(axis, single_function->axis());
}

TEST(InterpolatePropertyValueTest,
     TransformTranslateXFromLengthToPercentageValuesAnimate) {
  TestTransformTranslateFromLengthToPercentageValuesAnimate(
      TranslateFunction::kXAxis);
}
TEST(InterpolatePropertyValueTest,
     TransformTranslateYFromLengthToPercentageValuesAnimate) {
  TestTransformTranslateFromLengthToPercentageValuesAnimate(
      TranslateFunction::kYAxis);
}
TEST(InterpolatePropertyValueTest,
     TransformTranslateZFromLengthToPercentageValuesAnimate) {
  TestTransformTranslateFromLengthToPercentageValuesAnimate(
      TranslateFunction::kZAxis);
}

void TestTransformTranslateCalcValuesAnimate(TranslateFunction::Axis axis) {
  struct MakeSingleTranslateTransform {
    static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          axis, new CalcValue(new LengthValue(1.0f, kPixelsUnit),
                              new PercentageValue(0.2f))));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          axis, new CalcValue(new LengthValue(2.0f, kPixelsUnit),
                              new PercentageValue(0.4f))));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleTranslateTransform::Start(axis),
          MakeSingleTranslateTransform::End(axis));

  ASSERT_EQ(1, interpolated->value().size());
  const TranslateFunction* single_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  ASSERT_EQ(TranslateFunction::kCalc, single_function->offset_type());
  EXPECT_NEAR(1.5f, single_function->offset_as_calc()->length_value()->value(),
              kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit,
            single_function->offset_as_calc()->length_value()->unit());
  EXPECT_NEAR(0.3f,
              single_function->offset_as_calc()->percentage_value()->value(),
              kErrorEpsilon);
  EXPECT_EQ(axis, single_function->axis());
}

TEST(InterpolatePropertyValueTest, TestTransformTranslateXCalcValuesAnimate) {
  TestTransformTranslateCalcValuesAnimate(TranslateFunction::kXAxis);
}
TEST(InterpolatePropertyValueTest, TestTransformTranslateYCalcValuesAnimate) {
  TestTransformTranslateCalcValuesAnimate(TranslateFunction::kYAxis);
}
TEST(InterpolatePropertyValueTest, TestTransformTranslateZCalcValuesAnimate) {
  TestTransformTranslateCalcValuesAnimate(TranslateFunction::kZAxis);
}

void TestTransformFromTranslateToNoneValuesAnimate(
    TranslateFunction::Axis axis) {
  struct MakeSingleTranslateTransform {
    static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new TranslateFunction(axis, new LengthValue(1.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      return KeywordValue::GetNone();
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleTranslateTransform::Start(axis),
          MakeSingleTranslateTransform::End());

  ASSERT_EQ(1, interpolated->value().size());
  const TranslateFunction* single_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_NEAR(single_function->offset_as_length()->value(), 0.5f,
              kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit, single_function->offset_as_length()->unit());
  EXPECT_EQ(axis, single_function->axis());
}

TEST(InterpolatePropertyValueTest,
     TransformFromTranslateXToNoneValuesInterpolate) {
  TestTransformFromTranslateToNoneValuesAnimate(TranslateFunction::kXAxis);
}
TEST(InterpolatePropertyValueTest,
     TransformFromTranslateYToNoneValuesInterpolate) {
  TestTransformFromTranslateToNoneValuesAnimate(TranslateFunction::kYAxis);
}
TEST(InterpolatePropertyValueTest,
     TransformFromTranslateZToNoneValuesInterpolate) {
  TestTransformFromTranslateToNoneValuesAnimate(TranslateFunction::kZAxis);
}

TEST(InterpolatePropertyValueTest,
     CanAnimateTransformListWithMultipleElementsButSameSizeAndTypes) {
  struct MakeSingleScaleTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new RotateFunction(1.0f));
      functions.push_back(new ScaleFunction(1.0f, 2.0f));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis, new LengthValue(3.0f, kPixelsUnit)));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kYAxis, new LengthValue(4.0f, kPixelsUnit)));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kZAxis, new LengthValue(5.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new RotateFunction(2.0f));
      functions.push_back(new ScaleFunction(7.0f, 8.0f));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis, new LengthValue(9.0f, kPixelsUnit)));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kYAxis, new LengthValue(10.0f, kPixelsUnit)));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kZAxis, new LengthValue(11.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleScaleTransform::Start(),
          MakeSingleScaleTransform::End());

  ASSERT_EQ(5, interpolated->value().size());

  const RotateFunction* first_function =
      dynamic_cast<const RotateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(first_function);
  EXPECT_NEAR(first_function->clockwise_angle_in_radians(), 1.5f,
              kErrorEpsilon);

  const ScaleFunction* second_function =
      dynamic_cast<const ScaleFunction*>(interpolated->value()[1]);
  ASSERT_TRUE(second_function);
  EXPECT_NEAR(second_function->x_factor(), 4.0f, kErrorEpsilon);
  EXPECT_NEAR(second_function->y_factor(), 5.0f, kErrorEpsilon);

  const TranslateFunction* third_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[2]);
  ASSERT_TRUE(third_function);
  EXPECT_NEAR(third_function->offset_as_length()->value(), 6.0f, kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit, third_function->offset_as_length()->unit());

  const TranslateFunction* fourth_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[3]);
  ASSERT_TRUE(fourth_function);
  EXPECT_NEAR(fourth_function->offset_as_length()->value(), 7.0f,
              kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit, fourth_function->offset_as_length()->unit());

  const TranslateFunction* fifth_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[4]);
  ASSERT_TRUE(fifth_function);
  EXPECT_NEAR(fifth_function->offset_as_length()->value(), 8.0f, kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit, fifth_function->offset_as_length()->unit());
}

TEST(InterpolatePropertyValueTest,
     TransformSingleRotationMatrixValuesInterpolate) {
  struct MakeSingleMatrixTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new MatrixFunction(math::RotateMatrix(0.0f)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new MatrixFunction(math::RotateMatrix(static_cast<float>(M_PI / 2))));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleMatrixTransform::Start(),
          MakeSingleMatrixTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const MatrixFunction* single_function =
      dynamic_cast<const MatrixFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_TRUE(single_function->value().IsNear(
      math::RotateMatrix(static_cast<float>(M_PI / 4)), kErrorEpsilon));
}

TEST(InterpolatePropertyValueTest,
     TransformSingleScaleMatrixValuesInterpolate) {
  struct MakeSingleMatrixTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new MatrixFunction(math::ScaleMatrix(2.0f, 1.0f)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new MatrixFunction(math::ScaleMatrix(4.0f, 2.0f)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleMatrixTransform::Start(),
          MakeSingleMatrixTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const MatrixFunction* single_function =
      dynamic_cast<const MatrixFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_TRUE(single_function->value().IsNear(math::ScaleMatrix(3.0f, 1.5f),
                                              kErrorEpsilon));
}

TEST(InterpolatePropertyValueTest,
     TransformSingleTranslateMatrixValuesInterpolate) {
  struct MakeSingleMatrixTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new MatrixFunction(math::TranslateMatrix(2.0f, 1.0f)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(
          new MatrixFunction(math::TranslateMatrix(4.0f, 2.0f)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeSingleMatrixTransform::Start(),
          MakeSingleMatrixTransform::End());

  ASSERT_EQ(1, interpolated->value().size());

  const MatrixFunction* single_function =
      dynamic_cast<const MatrixFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);

  EXPECT_TRUE(single_function->value().IsNear(math::TranslateMatrix(3.0f, 1.5f),
                                              kErrorEpsilon));
}

TEST(InterpolatePropertyValueTest,
     MultipleMismatchedTransformValuesInterpolate) {
  struct MakeMultipleMismatchedTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis, new LengthValue(2.0f, kPixelsUnit)));
      functions.push_back(new ScaleFunction(2.0f, 1.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis, new LengthValue(4.0f, kPixelsUnit)));
      functions.push_back(new RotateFunction(static_cast<float>(M_PI / 2)));
      functions.push_back(new ScaleFunction(4.0f, 2.0f));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  // Since the original transform list had mismatched types, the result should
  // be a transform matrix.
  scoped_refptr<TransformMatrixFunctionValue> interpolated =
      InterpolatePropertyTyped<TransformMatrixFunctionValue>(
          0.75f, MakeMultipleMismatchedTransform::Start(),
          MakeMultipleMismatchedTransform::End());
  EXPECT_TRUE(interpolated->value().percentage_fields_zero());
  EXPECT_TRUE(
      interpolated->value()
          .ToMatrix3F(math::SizeF())
          .IsNear(math::TranslateMatrix(3.5f, 0.0f) *
                      math::RotateMatrix(-static_cast<float>(M_PI * 3 / 8)) *
                      math::ScaleMatrix(3.5f, 1.75f),
                  kErrorEpsilon));
}

TEST(InterpolatePropertyValueTest,
     RotationTransformMatrixTransitionsFromTransitions) {
  // Transition from a rotation transformation of 45 degrees to a translate
  // transformation of 0 (i.e. identity).  Since they are of different types,
  // we will invoke the "decompose to a matrix" path of transitioning a
  // transform, and then we c an simply test for the correct rotation value.
  struct MakeMultipleMismatchedTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis, new LengthValue(0.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new RotateFunction(static_cast<float>(M_PI / 2)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  // Since the original transform list had mismatched types, the result should
  // be a matrix.
  scoped_refptr<TransformMatrixFunctionValue> interpolated =
      InterpolatePropertyTyped<TransformMatrixFunctionValue>(
          0.5f, MakeMultipleMismatchedTransform::Start(),
          MakeMultipleMismatchedTransform::End());

  scoped_refptr<TransformMatrixFunctionValue> next_interpolated =
      InterpolatePropertyTyped<TransformMatrixFunctionValue>(
          0.5f, interpolated, MakeMultipleMismatchedTransform::Start());

  EXPECT_TRUE(next_interpolated->value().percentage_fields_zero());
  EXPECT_TRUE(next_interpolated->value()
                  .ToMatrix3F(math::SizeF())
                  .IsNear(math::RotateMatrix(-static_cast<float>(M_PI / 8)),
                          kErrorEpsilon));
}

TEST(InterpolatePropertyValueTest,
     CanInterpolateFromTranslateLengthToTranslatePercentage) {
  struct MakeMultipleMismatchedTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis, new LengthValue(5.0f, kPixelsUnit)));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(TranslateFunction::kXAxis,
                                                new PercentageValue(0.5f)));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  scoped_refptr<TransformFunctionListValue> interpolated =
      InterpolatePropertyTyped<TransformFunctionListValue>(
          0.5f, MakeMultipleMismatchedTransform::Start(),
          MakeMultipleMismatchedTransform::End());

  ASSERT_EQ(1, interpolated->value().size());
  const TranslateFunction* single_function =
      dynamic_cast<const TranslateFunction*>(interpolated->value()[0]);
  ASSERT_TRUE(single_function);
  EXPECT_EQ(TranslateFunction::kXAxis, single_function->axis());

  scoped_refptr<CalcValue> calc_value = single_function->offset_as_calc();
  EXPECT_NEAR(2.5f, calc_value->length_value()->value(), kErrorEpsilon);
  EXPECT_EQ(kPixelsUnit, calc_value->length_value()->unit());
  EXPECT_NEAR(0.25f, calc_value->percentage_value()->value(), kErrorEpsilon);
}

TEST(InterpolatePropertyValueTest,
     CanInterpolateMatricesWithPercentageAndOffsets) {
  struct MakeMultipleMismatchedTransform {
    static scoped_refptr<PropertyValue> Start() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis,
          new CalcValue(new LengthValue(2.0f, kPixelsUnit),
                        new PercentageValue(0.2f))));
      functions.push_back(new RotateFunction(static_cast<float>(M_PI / 2)));
      functions.push_back(new TranslateFunction(
          TranslateFunction::kXAxis,
          new CalcValue(new LengthValue(10.0f, kPixelsUnit),
                        new PercentageValue(1.0f))));
      return new TransformFunctionListValue(functions.Pass());
    }
    static scoped_refptr<PropertyValue> End() {
      TransformFunctionListValue::Builder functions;
      functions.push_back(new TranslateFunction(
          TranslateFunction::kYAxis,
          new CalcValue(new LengthValue(5.0f, kPixelsUnit),
                        new PercentageValue(0.5f))));
      return new TransformFunctionListValue(functions.Pass());
    }
  };

  // Since the original transform list had mismatched types, the result should
  // be a matrix.
  scoped_refptr<TransformMatrixFunctionValue> interpolated =
      InterpolatePropertyTyped<TransformMatrixFunctionValue>(
          0.5f, MakeMultipleMismatchedTransform::Start(),
          MakeMultipleMismatchedTransform::End());

  const TransformMatrix& value = interpolated->value();

  EXPECT_NEAR(cos(M_PI / 4), value.offset_matrix().Get(0, 0), kErrorEpsilon);
  EXPECT_NEAR(sin(M_PI / 4), value.offset_matrix().Get(1, 0), kErrorEpsilon);
  EXPECT_NEAR(-sin(M_PI / 4), value.offset_matrix().Get(0, 1), kErrorEpsilon);
  EXPECT_NEAR(cos(M_PI / 4), value.offset_matrix().Get(1, 1), kErrorEpsilon);
  EXPECT_NEAR(1.0f, value.offset_matrix().Get(0, 2), kErrorEpsilon);
  EXPECT_NEAR(7.5f, value.offset_matrix().Get(1, 2), kErrorEpsilon);

  EXPECT_NEAR(0.1f, value.width_percentage_translation().x(), kErrorEpsilon);
  EXPECT_NEAR(0.5f, value.width_percentage_translation().y(), kErrorEpsilon);
  EXPECT_NEAR(0.0f, value.height_percentage_translation().x(), kErrorEpsilon);
  EXPECT_NEAR(0.25f, value.height_percentage_translation().y(), kErrorEpsilon);
}

}  // namespace cssom
}  // namespace cobalt
