// 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 "cobalt/cssom/interpolate_property_value.h"

#include <algorithm>
#include <limits>

#include "base/memory/scoped_ptr.h"
#include "cobalt/base/enable_if.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/cssom/calc_value.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/length_value.h"
#include "cobalt/cssom/linear_gradient_value.h"
#include "cobalt/cssom/local_src_value.h"
#include "cobalt/cssom/matrix_function.h"
#include "cobalt/cssom/media_feature_keyword_value.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/cssom/property_key_list_value.h"
#include "cobalt/cssom/property_value_visitor.h"
#include "cobalt/cssom/rgba_color_value.h"
#include "cobalt/cssom/rotate_function.h"
#include "cobalt/cssom/scale_function.h"
#include "cobalt/cssom/string_value.h"
#include "cobalt/cssom/time_list_value.h"
#include "cobalt/cssom/timing_function_list_value.h"
#include "cobalt/cssom/transform_function.h"
#include "cobalt/cssom/transform_function_list_value.h"
#include "cobalt/cssom/transform_function_visitor.h"
#include "cobalt/cssom/transform_matrix_function_value.h"
#include "cobalt/cssom/translate_function.h"
#include "cobalt/cssom/unicode_range_value.h"
#include "cobalt/cssom/url_src_value.h"
#include "cobalt/cssom/url_value.h"
#include "cobalt/math/matrix_interpolation.h"
#include "cobalt/math/transform_2d.h"

namespace cobalt {
namespace cssom {

// This InterpolateVisitor allows us to define how to interpolate between
// a CSS style value, for each different CSS style value.  Input to the visitor
// conceptually is a start CSS style value and an end CSS style value that are
// of the same type.  Technically though, we can only visit on one of them, so
// the end value is passed into the constructor and the start value is visited.
//   https://www.w3.org/TR/css3-transitions/#animatable-types
class InterpolateVisitor : public PropertyValueVisitor {
 public:
  InterpolateVisitor(const scoped_refptr<PropertyValue>& end_value,
                     float progress)
      : end_value_(end_value), progress_(progress) {}

  const scoped_refptr<PropertyValue>& interpolated_value() const {
    return interpolated_value_;
  }

  void VisitAbsoluteURL(AbsoluteURLValue* start_absolute_url_value) OVERRIDE;
  void VisitCalc(CalcValue* start_calc_value) OVERRIDE;
  void VisitFilterFunctionList(
      FilterFunctionListValue* start_filter_function_list_value) OVERRIDE;
  void VisitFontStyle(FontStyleValue* start_font_style_value) OVERRIDE;
  void VisitFontWeight(FontWeightValue* start_font_weight_value) OVERRIDE;
  void VisitInteger(IntegerValue* integer_value) OVERRIDE;
  void VisitKeyword(KeywordValue* start_keyword_value) OVERRIDE;
  void VisitLength(LengthValue* start_length_value) OVERRIDE;
  void VisitLinearGradient(
      LinearGradientValue* start_linear_gradient_value) OVERRIDE;
  void VisitLocalSrc(LocalSrcValue* local_src_value) OVERRIDE;
  void VisitMediaFeatureKeywordValue(
      MediaFeatureKeywordValue* media_feature_keyword_value) OVERRIDE;
  void VisitNumber(NumberValue* start_number_value) OVERRIDE;
  void VisitPercentage(PercentageValue* start_percentage_value) OVERRIDE;
  void VisitPropertyList(PropertyListValue* property_list_value) OVERRIDE;
  void VisitPropertyKeyList(
      PropertyKeyListValue* property_key_list_value) OVERRIDE;
  void VisitRadialGradient(RadialGradientValue* radial_gradient_value) OVERRIDE;
  void VisitRatio(RatioValue* start_ratio_value) OVERRIDE;
  void VisitResolution(ResolutionValue* start_resolution_value) OVERRIDE;
  void VisitRGBAColor(RGBAColorValue* start_color_value) OVERRIDE;
  void VisitShadow(ShadowValue* shadow_value) OVERRIDE;
  void VisitString(StringValue* start_string_value) OVERRIDE;
  void VisitTransformFunctionList(
      TransformFunctionListValue* start_transform_list_value) OVERRIDE;
  void VisitTransformMatrixFunction(
      TransformMatrixFunctionValue* transform_matrix_function_value) OVERRIDE;
  void VisitTimeList(TimeListValue* start_time_list_value) OVERRIDE;
  void VisitTimingFunctionList(
      TimingFunctionListValue* start_timing_function_list_value) OVERRIDE;
  void VisitUnicodeRange(UnicodeRangeValue* unicode_range_value) OVERRIDE;
  void VisitURL(URLValue* url_value) OVERRIDE;
  void VisitUrlSrc(UrlSrcValue* url_src_value) OVERRIDE;

 private:
  scoped_refptr<PropertyValue> end_value_;
  float progress_;

  scoped_refptr<PropertyValue> interpolated_value_;
};

namespace {

// Round to nearest integer for integer types.
template <typename T>
typename base::enable_if<std::numeric_limits<T>::is_integer, T>::type Round(
    float value) {
  return static_cast<T>(value + 0.5);
}

// Pass through the value in the case of non-integer types.
template <typename T>
typename base::enable_if<!std::numeric_limits<T>::is_integer, T>::type Round(
    float value) {
  return static_cast<T>(value);
}

// Linearly interpolate from value a to value b, and then apply a round on the
// results before returning if we are interpolating integer types (as specified
// by https://www.w3.org/TR/css3-transitions/#animatable-types).
template <typename T>
T Lerp(const T& a, const T& b, float progress) {
  return Round<T>(a * (1 - progress) + b * progress);
}

}  // namespace

namespace {
// Defines how each different type of transform function should be animated.
class AnimateTransformFunction : public TransformFunctionVisitor {
 public:
  // Returns an animated version of the transform function given the start, end
  // and progress.  Note that end may be NULL if the destination transform is
  // 'none'.  In this case, we should use an appropriate identity transform
  // to animate towards.
  static scoped_ptr<TransformFunction> Animate(const TransformFunction* start,
                                               const TransformFunction* end,
                                               float progress) {
    AnimateTransformFunction visitor(end, progress);
    const_cast<TransformFunction*>(start)->Accept(&visitor);
    return visitor.animated_.Pass();
  }

 private:
  void VisitMatrix(const MatrixFunction* matrix_function) OVERRIDE;
  void VisitRotate(const RotateFunction* rotate_function) OVERRIDE;
  void VisitScale(const ScaleFunction* scale_function) OVERRIDE;
  void VisitTranslate(const TranslateFunction* translate_function) OVERRIDE;

  AnimateTransformFunction(const TransformFunction* end, float progress)
      : end_(end), progress_(progress) {}

  const TransformFunction* end_;
  float progress_;
  scoped_ptr<TransformFunction> animated_;
};

void AnimateTransformFunction::VisitMatrix(
    const MatrixFunction* matrix_function) {
  const MatrixFunction* matrix_end =
      base::polymorphic_downcast<const MatrixFunction*>(end_);
  math::Matrix3F interpolated_matrix = math::InterpolateMatrices(
      matrix_function->value(),
      matrix_end ? matrix_end->value() : math::Matrix3F::Identity(), progress_);

  animated_.reset(new MatrixFunction(interpolated_matrix));
}

void AnimateTransformFunction::VisitRotate(
    const RotateFunction* rotate_function) {
  const RotateFunction* rotate_end =
      base::polymorphic_downcast<const RotateFunction*>(end_);

  // The rotate function's identity is the value 0.
  float end_angle =
      rotate_end ? rotate_end->clockwise_angle_in_radians() : 0.0f;

  animated_.reset(new RotateFunction(Lerp(
      rotate_function->clockwise_angle_in_radians(), end_angle, progress_)));
}

void AnimateTransformFunction::VisitScale(const ScaleFunction* scale_function) {
  float end_x_factor, end_y_factor;
  if (end_ == NULL) {
    // Use the scale identity function, which is the value 1.
    end_x_factor = 1.0f;
    end_y_factor = 1.0f;
  } else {
    const ScaleFunction* end_scale =
        base::polymorphic_downcast<const ScaleFunction*>(end_);
    end_x_factor = end_scale->x_factor();
    end_y_factor = end_scale->y_factor();
  }

  animated_.reset(new ScaleFunction(
      Lerp(scale_function->x_factor(), end_x_factor, progress_),
      Lerp(scale_function->y_factor(), end_y_factor, progress_)));
}

namespace {
scoped_ptr<TranslateFunction> InterpolateTranslateFunctions(
    const TranslateFunction* a, const TranslateFunction* b, float progress) {
  if (b) {
    DCHECK_EQ(a->axis(), b->axis());
  }

  float end_length_offset = b ? b->length_component_in_pixels() : 0.0f;
  float lerped_length_offset =
      Lerp(a->length_component_in_pixels(), end_length_offset, progress);

  float end_percentage_offset = b ? b->percentage_component() : 0.0f;
  float lerped_percentage_offset =
      Lerp(a->percentage_component(), end_percentage_offset, progress);

  bool result_is_calc = (b && a->offset_type() != b->offset_type()) ||
                        a->offset_type() == TranslateFunction::kCalc;

  if (result_is_calc) {
    return make_scoped_ptr(new TranslateFunction(
        a->axis(),
        new CalcValue(new LengthValue(lerped_length_offset, kPixelsUnit),
                      new PercentageValue(lerped_percentage_offset))));
  } else if (a->offset_type() == TranslateFunction::kLength) {
    DCHECK_EQ(0.0f, lerped_percentage_offset);
    return make_scoped_ptr(new TranslateFunction(
        a->axis(), new LengthValue(lerped_length_offset, kPixelsUnit)));
  } else if (a->offset_type() == TranslateFunction::kPercentage) {
    DCHECK_EQ(0.0f, lerped_length_offset);
    return make_scoped_ptr(new TranslateFunction(
        a->axis(), new PercentageValue(lerped_percentage_offset)));
  } else {
    NOTREACHED();
    return scoped_ptr<TranslateFunction>();
  }
}
}  // namespace

void AnimateTransformFunction::VisitTranslate(
    const TranslateFunction* translate_function) {
  const TranslateFunction* translate_end =
      base::polymorphic_downcast<const TranslateFunction*>(end_);

  animated_ = InterpolateTranslateFunctions(translate_function, translate_end,
                                            progress_);
}

// Returns true if two given transform function lists have the same number of
// elements, and each element type matches the corresponding element type at
// the same index in the other list.
bool TransformListsHaveSameType(const TransformFunctionListValue::Builder& a,
                                const TransformFunctionListValue::Builder& b) {
  if (a.size() != b.size()) {
    return false;
  }

  for (size_t i = 0; i < a.size(); ++i) {
    if (a[i]->GetTypeId() != b[i]->GetTypeId()) {
      return false;
    } else if (a[i]->GetTypeId() == base::GetTypeId<TranslateFunction>() &&
               base::polymorphic_downcast<const TranslateFunction*>(a[i])
                       ->axis() !=
                   base::polymorphic_downcast<const TranslateFunction*>(b[i])
                       ->axis()) {
      return false;
    }
  }
  return true;
}

scoped_refptr<PropertyValue> AnimateTransform(const PropertyValue* start_value,
                                              const PropertyValue* end_value,
                                              float progress) {
  // The process for animating a transform list are described here:
  //  https://www.w3.org/TR/2012/WD-css3-transforms-20120228/#animation

  // If both start and end values are "none", then the animated value is
  // "none" also and we are done.
  if (start_value->Equals(*KeywordValue::GetNone()) &&
      end_value->Equals(*KeywordValue::GetNone())) {
    return KeywordValue::GetNone();
  }

  // At this point, either start_value or end_value may be "none" (though not
  // both).  We shuffle things around here to ensure that start_value is always
  // not "none" so that subsequent code is simplified.
  if (start_value->Equals(*KeywordValue::GetNone())) {
    std::swap(start_value, end_value);
    progress = 1 - progress;
  }

  const TransformFunctionListValue* start_transform =
      base::polymorphic_downcast<const TransformFunctionListValue*>(
          start_value);
  const TransformFunctionListValue* end_transform =
      end_value->Equals(*KeywordValue::GetNone())
          ? NULL
          : base::polymorphic_downcast<const TransformFunctionListValue*>(
                end_value);

  const TransformFunctionListValue::Builder* start_functions =
      &start_transform->value();

  const TransformFunctionListValue::Builder* end_functions =
      end_transform ? &end_transform->value() : NULL;

  // We first check to see if there is a match between transform types in
  // the start transform list and transform types in the end transform list.
  // This is necessary to know how to proceed in animating this transform.
  // Note that a value of "none" implies that we will use identity transforms
  // for that transform list, so in that case, there is indeed a match.
  bool matching_list_types =
      end_functions == NULL ||
      TransformListsHaveSameType(*start_functions, *end_functions);
  if (matching_list_types) {
    TransformFunctionListValue::Builder animated_functions;
    // The lists have the same number of values and each corresponding transform
    // matches in type.  In this case, we do a transition on each
    // corresponding transform individually.
    for (size_t i = 0; i < start_functions->size(); ++i) {
      animated_functions.push_back(
          AnimateTransformFunction::Animate(
              (*start_functions)[i], end_functions ? (*end_functions)[i] : NULL,
              progress)
              .release());
    }
    return new TransformFunctionListValue(animated_functions.Pass());
  } else {
    // The transform lists do not match up type for type. Collapse each list
    // into a matrix and animate the matrix using the algorithm described here:
    //   https://www.w3.org/TR/2012/WD-css3-transforms-20120228/#matrix-decomposition
    DCHECK(end_transform);
    return new TransformMatrixFunctionValue(InterpolateTransformMatrices(
        start_transform->ToMatrix(), end_transform->ToMatrix(), progress));
  }
}
}  // namespace

void InterpolateVisitor::VisitAbsoluteURL(
    AbsoluteURLValue* /*start_absolute_url_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitCalc(CalcValue* /*start_calc_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitFilterFunctionList(
    FilterFunctionListValue* /*start_filter_function_list_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitFontStyle(
    FontStyleValue* /*start_font_style_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitFontWeight(
    FontWeightValue* /*start_font_weight_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitInteger(IntegerValue* integer_value) {
  UNREFERENCED_PARAMETER(integer_value);
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitKeyword(KeywordValue* start_keyword_value) {
  if (start_keyword_value->Equals(*end_value_)) {
    interpolated_value_ = start_keyword_value;
  }

  if (start_keyword_value->value() == KeywordValue::kNone) {
    if (end_value_->GetTypeId() ==
        base::GetTypeId<TransformFunctionListValue>()) {
      interpolated_value_ =
          AnimateTransform(start_keyword_value, end_value_, progress_);
    }
  } else {
    NOTREACHED();
  }
}

void InterpolateVisitor::VisitLength(LengthValue* start_length_value) {
  const LengthValue& end_length_value =
      *base::polymorphic_downcast<LengthValue*>(end_value_.get());
  interpolated_value_ = scoped_refptr<PropertyValue>(new LengthValue(
      Lerp(start_length_value->value(), end_length_value.value(), progress_),
      cssom::kPixelsUnit));
}

void InterpolateVisitor::VisitLinearGradient(
    LinearGradientValue* /*start_linear_gradient_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitLocalSrc(LocalSrcValue* /*local_src_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitMediaFeatureKeywordValue(
    MediaFeatureKeywordValue* /*media_feature_keyword_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitNumber(NumberValue* start_number_value) {
  DCHECK(start_number_value->GetTypeId() == end_value_->GetTypeId());
  const NumberValue& end_number_value =
      *base::polymorphic_downcast<NumberValue*>(end_value_.get());

  interpolated_value_ = scoped_refptr<PropertyValue>(new NumberValue(
      Lerp(start_number_value->value(), end_number_value.value(), progress_)));
}

void InterpolateVisitor::VisitPercentage(
    PercentageValue* /*start_percentage_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitPropertyList(
    PropertyListValue* /*property_list_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitPropertyKeyList(
    PropertyKeyListValue* /*property_key_list_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitRadialGradient(
    RadialGradientValue* /*radial_gradient_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitRatio(RatioValue* /*start_ratio_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitResolution(
    ResolutionValue* /*start_resolution_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitRGBAColor(RGBAColorValue* start_color_value) {
  DCHECK(start_color_value->GetTypeId() == end_value_->GetTypeId());
  const RGBAColorValue& end_color_value =
      *base::polymorphic_downcast<RGBAColorValue*>(end_value_.get());

  interpolated_value_ = scoped_refptr<PropertyValue>(new RGBAColorValue(
      Lerp(start_color_value->r(), end_color_value.r(), progress_),
      Lerp(start_color_value->g(), end_color_value.g(), progress_),
      Lerp(start_color_value->b(), end_color_value.b(), progress_),
      Lerp(start_color_value->a(), end_color_value.a(), progress_)));
}

void InterpolateVisitor::VisitShadow(ShadowValue* /*shadow_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitString(StringValue* /*start_string_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitTimeList(
    TimeListValue* /*start_time_list_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

namespace {
// Returns a TransformMatrix representing a valid 'transform' property value.
TransformMatrix GetTransformMatrixFromPropertyValue(
    const PropertyValue* value) {
  if (value->Equals(*KeywordValue::GetNone())) {
    // Return the identity matrix via the default constructor.
    return TransformMatrix();
  } else if (value->GetTypeId() ==
             base::GetTypeId<TransformFunctionListValue>()) {
    return base::polymorphic_downcast<const TransformFunctionListValue*>(value)
        ->ToMatrix();
  } else if (value->GetTypeId() ==
             base::GetTypeId<TransformMatrixFunctionValue>()) {
    return base::polymorphic_downcast<const TransformMatrixFunctionValue*>(
               value)
        ->value();
  } else {
    NOTREACHED();
    return TransformMatrix();
  }
}

// Converts some given valid 'transform' property values to TransformMatrices,
// and then interpolates them and returns the result.
scoped_refptr<TransformMatrixFunctionValue> InterpolateTransformsAsMatrices(
    const PropertyValue* a, const PropertyValue* b, float progress) {
  return new TransformMatrixFunctionValue(InterpolateTransformMatrices(
      GetTransformMatrixFromPropertyValue(a),
      GetTransformMatrixFromPropertyValue(b), progress));
}
}  // namespace

void InterpolateVisitor::VisitTransformFunctionList(
    TransformFunctionListValue* start_transform_list_value) {
  if (end_value_->GetTypeId() ==
      base::GetTypeId<TransformMatrixFunctionValue>()) {
    // If our end value is a transform matrix, then simply convert to a
    // transform matrix and interpolate between them.
    interpolated_value_ = InterpolateTransformsAsMatrices(
        start_transform_list_value, end_value_, progress_);
  } else {
    // If we are not dealing with a transform matrix, then animate the
    // transform lists, attempting to keep the list structure as the result
    // if possible (as opposed to converting to a matrix and interpolating that,
    // resulting in a matrix).
    interpolated_value_ =
        AnimateTransform(start_transform_list_value, end_value_, progress_);
  }
}

void InterpolateVisitor::VisitTransformMatrixFunction(
    TransformMatrixFunctionValue* start_transform_matrix_function_value) {
  interpolated_value_ = InterpolateTransformsAsMatrices(
      start_transform_matrix_function_value, end_value_, progress_);
}

void InterpolateVisitor::VisitTimingFunctionList(
    TimingFunctionListValue* /*start_timing_function_list_value*/) {
  NOTIMPLEMENTED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitUnicodeRange(
    UnicodeRangeValue* /*unicode_range_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitURL(URLValue* /*url_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

void InterpolateVisitor::VisitUrlSrc(UrlSrcValue* /*url_src_value*/) {
  NOTREACHED();
  interpolated_value_ = end_value_;
}

scoped_refptr<PropertyValue> InterpolatePropertyValue(
    float progress, const scoped_refptr<PropertyValue>& start_value,
    const scoped_refptr<PropertyValue>& end_value) {
  InterpolateVisitor visitor(end_value, progress);
  start_value->Accept(&visitor);

  return visitor.interpolated_value();
}

}  // namespace cssom
}  // namespace cobalt
