/*
 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008 Apple Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2012. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/svg/SVGTransformList.h"

#include "core/css/CSSFunctionValue.h"
#include "core/css/CSSIdentifierValue.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSValueList.h"
#include "core/svg/SVGParserUtilities.h"
#include "core/svg/SVGTransformDistance.h"
#include "core/svg_names.h"
#include "platform/wtf/text/ParsingUtilities.h"
#include "platform/wtf/text/StringBuilder.h"
#include "platform/wtf/text/WTFString.h"

namespace blink {

SVGTransformList::SVGTransformList() = default;

SVGTransformList::~SVGTransformList() = default;

SVGTransform* SVGTransformList::Consolidate() {
  AffineTransform matrix;
  if (!Concatenate(matrix))
    return nullptr;

  return Initialize(SVGTransform::Create(matrix));
}

bool SVGTransformList::Concatenate(AffineTransform& result) const {
  if (IsEmpty())
    return false;

  ConstIterator it = begin();
  ConstIterator it_end = end();
  for (; it != it_end; ++it)
    result *= it->Matrix();

  return true;
}

namespace {

CSSValueID MapTransformFunction(const SVGTransform& transform) {
  switch (transform.TransformType()) {
    case kSvgTransformMatrix:
      return CSSValueMatrix;
    case kSvgTransformTranslate:
      return CSSValueTranslate;
    case kSvgTransformScale:
      return CSSValueScale;
    case kSvgTransformRotate:
      return CSSValueRotate;
    case kSvgTransformSkewx:
      return CSSValueSkewX;
    case kSvgTransformSkewy:
      return CSSValueSkewY;
    case kSvgTransformUnknown:
    default:
      NOTREACHED();
  }
  return CSSValueInvalid;
}

CSSValue* CreateTransformCSSValue(const SVGTransform& transform) {
  CSSValueID function_id = MapTransformFunction(transform);
  CSSFunctionValue* transform_value = CSSFunctionValue::Create(function_id);
  switch (function_id) {
    case CSSValueRotate: {
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Angle(), CSSPrimitiveValue::UnitType::kDegrees));
      FloatPoint rotation_origin = transform.RotationCenter();
      if (!ToFloatSize(rotation_origin).IsZero()) {
        transform_value->Append(*CSSPrimitiveValue::Create(
            rotation_origin.X(), CSSPrimitiveValue::UnitType::kUserUnits));
        transform_value->Append(*CSSPrimitiveValue::Create(
            rotation_origin.Y(), CSSPrimitiveValue::UnitType::kUserUnits));
      }
      break;
    }
    case CSSValueSkewX:
    case CSSValueSkewY:
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Angle(), CSSPrimitiveValue::UnitType::kDegrees));
      break;
    case CSSValueMatrix:
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().A(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().B(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().C(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().D(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().E(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().F(), CSSPrimitiveValue::UnitType::kUserUnits));
      break;
    case CSSValueScale:
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().A(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().D(), CSSPrimitiveValue::UnitType::kUserUnits));
      break;
    case CSSValueTranslate:
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().E(), CSSPrimitiveValue::UnitType::kUserUnits));
      transform_value->Append(*CSSPrimitiveValue::Create(
          transform.Matrix().F(), CSSPrimitiveValue::UnitType::kUserUnits));
      break;
    default:
      NOTREACHED();
  }
  return transform_value;
}

}  // namespace

const CSSValue* SVGTransformList::CssValue() const {
  // Build a structure of CSSValues from the list we have, mapping functions as
  // appropriate.
  // TODO(fs): Eventually we'd want to support the exact same syntax here as in
  // the property, but there are some issues (crbug.com/577219 for instance)
  // that complicates things.
  size_t length = this->length();
  if (!length)
    return CSSIdentifierValue::Create(CSSValueNone);
  CSSValueList* list = CSSValueList::CreateSpaceSeparated();
  if (length == 1) {
    list->Append(*CreateTransformCSSValue(*at(0)));
    return list;
  }
  ConstIterator it = begin();
  ConstIterator it_end = end();
  for (; it != it_end; ++it)
    list->Append(*CreateTransformCSSValue(**it));
  return list;
}

namespace {

template <typename CharType>
SVGTransformType ParseAndSkipTransformType(const CharType*& ptr,
                                           const CharType* end) {
  if (ptr >= end)
    return kSvgTransformUnknown;

  if (*ptr == 's') {
    if (SkipToken(ptr, end, "skewX"))
      return kSvgTransformSkewx;
    if (SkipToken(ptr, end, "skewY"))
      return kSvgTransformSkewy;
    if (SkipToken(ptr, end, "scale"))
      return kSvgTransformScale;

    return kSvgTransformUnknown;
  }
  if (SkipToken(ptr, end, "translate"))
    return kSvgTransformTranslate;
  if (SkipToken(ptr, end, "rotate"))
    return kSvgTransformRotate;
  if (SkipToken(ptr, end, "matrix"))
    return kSvgTransformMatrix;

  return kSvgTransformUnknown;
}

// These should be kept in sync with enum SVGTransformType
const unsigned kRequiredValuesForType[] = {0, 6, 1, 1, 1, 1, 1};
const unsigned kOptionalValuesForType[] = {0, 0, 1, 1, 2, 0, 0};
static_assert(kSvgTransformUnknown == 0,
              "index of kSvgTransformUnknown has changed");
static_assert(kSvgTransformMatrix == 1,
              "index of kSvgTransformMatrix has changed");
static_assert(kSvgTransformTranslate == 2,
              "index of kSvgTransformTranslate has changed");
static_assert(kSvgTransformScale == 3,
              "index of kSvgTransformScale has changed");
static_assert(kSvgTransformRotate == 4,
              "index of kSvgTransformRotate has changed");
static_assert(kSvgTransformSkewx == 5,
              "index of kSvgTransformSkewx has changed");
static_assert(kSvgTransformSkewy == 6,
              "index of kSvgTransformSkewy has changed");
static_assert(WTF_ARRAY_LENGTH(kRequiredValuesForType) - 1 ==
                  kSvgTransformSkewy,
              "the number of transform types have changed");
static_assert(WTF_ARRAY_LENGTH(kRequiredValuesForType) ==
                  WTF_ARRAY_LENGTH(kOptionalValuesForType),
              "the arrays should have the same number of elements");

const unsigned kMaxTransformArguments = 6;

using TransformArguments = Vector<float, kMaxTransformArguments>;

template <typename CharType>
SVGParseStatus ParseTransformArgumentsForType(SVGTransformType type,
                                              const CharType*& ptr,
                                              const CharType* end,
                                              TransformArguments& arguments) {
  const size_t required = kRequiredValuesForType[type];
  const size_t optional = kOptionalValuesForType[type];
  const size_t required_with_optional = required + optional;
  DCHECK_LE(required_with_optional, kMaxTransformArguments);
  DCHECK(arguments.IsEmpty());

  bool trailing_delimiter = false;

  while (arguments.size() < required_with_optional) {
    float argument_value = 0;
    if (!ParseNumber(ptr, end, argument_value, kAllowLeadingWhitespace))
      break;

    arguments.push_back(argument_value);
    trailing_delimiter = false;

    if (arguments.size() == required_with_optional)
      break;

    if (SkipOptionalSVGSpaces(ptr, end) && *ptr == ',') {
      ++ptr;
      trailing_delimiter = true;
    }
  }

  if (arguments.size() != required &&
      arguments.size() != required_with_optional)
    return SVGParseStatus::kExpectedNumber;
  if (trailing_delimiter)
    return SVGParseStatus::kTrailingGarbage;

  return SVGParseStatus::kNoError;
}

SVGTransform* CreateTransformFromValues(SVGTransformType type,
                                        const TransformArguments& arguments) {
  SVGTransform* transform = SVGTransform::Create();
  switch (type) {
    case kSvgTransformSkewx:
      transform->SetSkewX(arguments[0]);
      break;
    case kSvgTransformSkewy:
      transform->SetSkewY(arguments[0]);
      break;
    case kSvgTransformScale:
      // Spec: if only one param given, assume uniform scaling.
      if (arguments.size() == 1)
        transform->SetScale(arguments[0], arguments[0]);
      else
        transform->SetScale(arguments[0], arguments[1]);
      break;
    case kSvgTransformTranslate:
      // Spec: if only one param given, assume 2nd param to be 0.
      if (arguments.size() == 1)
        transform->SetTranslate(arguments[0], 0);
      else
        transform->SetTranslate(arguments[0], arguments[1]);
      break;
    case kSvgTransformRotate:
      if (arguments.size() == 1)
        transform->SetRotate(arguments[0], 0, 0);
      else
        transform->SetRotate(arguments[0], arguments[1], arguments[2]);
      break;
    case kSvgTransformMatrix:
      transform->SetMatrix(AffineTransform(arguments[0], arguments[1],
                                           arguments[2], arguments[3],
                                           arguments[4], arguments[5]));
      break;
    case kSvgTransformUnknown:
      NOTREACHED();
      break;
  }
  return transform;
}

}  // namespace

template <typename CharType>
SVGParsingError SVGTransformList::ParseInternal(const CharType*& ptr,
                                                const CharType* end) {
  Clear();

  const CharType* start = ptr;
  bool delim_parsed = false;
  while (SkipOptionalSVGSpaces(ptr, end)) {
    delim_parsed = false;

    SVGTransformType transform_type = ParseAndSkipTransformType(ptr, end);
    if (transform_type == kSvgTransformUnknown)
      return SVGParsingError(SVGParseStatus::kExpectedTransformFunction,
                             ptr - start);

    if (!SkipOptionalSVGSpaces(ptr, end) || *ptr != '(')
      return SVGParsingError(SVGParseStatus::kExpectedStartOfArguments,
                             ptr - start);
    ptr++;

    TransformArguments arguments;
    SVGParseStatus status =
        ParseTransformArgumentsForType(transform_type, ptr, end, arguments);
    if (status != SVGParseStatus::kNoError)
      return SVGParsingError(status, ptr - start);
    DCHECK_GE(arguments.size(), kRequiredValuesForType[transform_type]);

    if (!SkipOptionalSVGSpaces(ptr, end) || *ptr != ')')
      return SVGParsingError(SVGParseStatus::kExpectedEndOfArguments,
                             ptr - start);
    ptr++;

    Append(CreateTransformFromValues(transform_type, arguments));

    if (SkipOptionalSVGSpaces(ptr, end) && *ptr == ',') {
      ++ptr;
      delim_parsed = true;
    }
  }
  if (delim_parsed)
    return SVGParsingError(SVGParseStatus::kTrailingGarbage, ptr - start);
  return SVGParseStatus::kNoError;
}

bool SVGTransformList::Parse(const UChar*& ptr, const UChar* end) {
  return ParseInternal(ptr, end) == SVGParseStatus::kNoError;
}

bool SVGTransformList::Parse(const LChar*& ptr, const LChar* end) {
  return ParseInternal(ptr, end) == SVGParseStatus::kNoError;
}

SVGTransformType ParseTransformType(const String& string) {
  if (string.IsEmpty())
    return kSvgTransformUnknown;
  if (string.Is8Bit()) {
    const LChar* ptr = string.Characters8();
    const LChar* end = ptr + string.length();
    return ParseAndSkipTransformType(ptr, end);
  }
  const UChar* ptr = string.Characters16();
  const UChar* end = ptr + string.length();
  return ParseAndSkipTransformType(ptr, end);
}

String SVGTransformList::ValueAsString() const {
  StringBuilder builder;

  ConstIterator it = begin();
  ConstIterator it_end = end();
  while (it != it_end) {
    builder.Append(it->ValueAsString());
    ++it;
    if (it != it_end)
      builder.Append(' ');
  }

  return builder.ToString();
}

SVGParsingError SVGTransformList::SetValueAsString(const String& value) {
  if (value.IsEmpty()) {
    Clear();
    return SVGParseStatus::kNoError;
  }

  SVGParsingError parse_error;
  if (value.Is8Bit()) {
    const LChar* ptr = value.Characters8();
    const LChar* end = ptr + value.length();
    parse_error = ParseInternal(ptr, end);
  } else {
    const UChar* ptr = value.Characters16();
    const UChar* end = ptr + value.length();
    parse_error = ParseInternal(ptr, end);
  }

  if (parse_error != SVGParseStatus::kNoError)
    Clear();

  return parse_error;
}

SVGPropertyBase* SVGTransformList::CloneForAnimation(
    const String& value) const {
  DCHECK(RuntimeEnabledFeatures::WebAnimationsSVGEnabled());
  return SVGListPropertyHelper::CloneForAnimation(value);
}

SVGTransformList* SVGTransformList::Create(SVGTransformType transform_type,
                                           const String& value) {
  TransformArguments arguments;
  bool at_end_of_value = false;
  SVGParseStatus status = SVGParseStatus::kParsingFailed;
  if (value.IsEmpty()) {
  } else if (value.Is8Bit()) {
    const LChar* ptr = value.Characters8();
    const LChar* end = ptr + value.length();
    status =
        ParseTransformArgumentsForType(transform_type, ptr, end, arguments);
    at_end_of_value = !SkipOptionalSVGSpaces(ptr, end);
  } else {
    const UChar* ptr = value.Characters16();
    const UChar* end = ptr + value.length();
    status =
        ParseTransformArgumentsForType(transform_type, ptr, end, arguments);
    at_end_of_value = !SkipOptionalSVGSpaces(ptr, end);
  }

  SVGTransformList* svg_transform_list = SVGTransformList::Create();
  if (at_end_of_value && status == SVGParseStatus::kNoError)
    svg_transform_list->Append(
        CreateTransformFromValues(transform_type, arguments));
  return svg_transform_list;
}

void SVGTransformList::Add(SVGPropertyBase* other,
                           SVGElement* context_element) {
  if (IsEmpty())
    return;

  SVGTransformList* other_list = ToSVGTransformList(other);
  if (length() != other_list->length())
    return;

  DCHECK_EQ(length(), 1u);
  SVGTransform* from_transform = at(0);
  SVGTransform* to_transform = other_list->at(0);

  DCHECK_EQ(from_transform->TransformType(), to_transform->TransformType());
  Initialize(
      SVGTransformDistance::AddSVGTransforms(from_transform, to_transform));
}

void SVGTransformList::CalculateAnimatedValue(
    SVGAnimationElement* animation_element,
    float percentage,
    unsigned repeat_count,
    SVGPropertyBase* from_value,
    SVGPropertyBase* to_value,
    SVGPropertyBase* to_at_end_of_duration_value,
    SVGElement* context_element) {
  DCHECK(animation_element);
  bool is_to_animation = animation_element->GetAnimationMode() == kToAnimation;

  // Spec: To animations provide specific functionality to get a smooth change
  // from the underlying value to the 'to' attribute value, which conflicts
  // mathematically with the requirement for additive transform animations to be
  // post-multiplied. As a consequence, in SVG 1.1 the behavior of to animations
  // for 'animateTransform' is undefined.
  // FIXME: This is not taken into account yet.
  SVGTransformList* from_list =
      is_to_animation ? this : ToSVGTransformList(from_value);
  SVGTransformList* to_list = ToSVGTransformList(to_value);
  SVGTransformList* to_at_end_of_duration_list =
      ToSVGTransformList(to_at_end_of_duration_value);

  size_t to_list_size = to_list->length();
  if (!to_list_size)
    return;

  // Get a reference to the from value before potentially cleaning it out (in
  // the case of a To animation.)
  SVGTransform* to_transform = to_list->at(0);
  SVGTransform* effective_from = nullptr;
  // If there's an existing 'from'/underlying value of the same type use that,
  // else use a "zero transform".
  if (from_list->length() &&
      from_list->at(0)->TransformType() == to_transform->TransformType())
    effective_from = from_list->at(0);
  else
    effective_from = SVGTransform::Create(
        to_transform->TransformType(), SVGTransform::kConstructZeroTransform);

  // Never resize the animatedTransformList to the toList size, instead either
  // clear the list or append to it.
  if (!IsEmpty() && (!animation_element->IsAdditive() || is_to_animation))
    Clear();

  SVGTransform* current_transform =
      SVGTransformDistance(effective_from, to_transform)
          .ScaledDistance(percentage)
          .AddToSVGTransform(effective_from);
  if (animation_element->IsAccumulated() && repeat_count) {
    SVGTransform* effective_to_at_end =
        !to_at_end_of_duration_list->IsEmpty()
            ? to_at_end_of_duration_list->at(0)
            : SVGTransform::Create(to_transform->TransformType(),
                                   SVGTransform::kConstructZeroTransform);
    Append(SVGTransformDistance::AddSVGTransforms(
        current_transform, effective_to_at_end, repeat_count));
  } else {
    Append(current_transform);
  }
}

float SVGTransformList::CalculateDistance(SVGPropertyBase* to_value,
                                          SVGElement*) {
  // FIXME: This is not correct in all cases. The spec demands that each
  // component (translate x and y for example) is paced separately. To implement
  // this we need to treat each component as individual animation everywhere.

  SVGTransformList* to_list = ToSVGTransformList(to_value);
  if (IsEmpty() || length() != to_list->length())
    return -1;

  DCHECK_EQ(length(), 1u);
  if (at(0)->TransformType() == to_list->at(0)->TransformType())
    return -1;

  // Spec: http://www.w3.org/TR/SVG/animate.html#complexDistances
  // Paced animations assume a notion of distance between the various animation
  // values defined by the 'to', 'from', 'by' and 'values' attributes.  Distance
  // is defined only for scalar types (such as <length>), colors and the subset
  // of transformation types that are supported by 'animateTransform'.
  return SVGTransformDistance(at(0), to_list->at(0)).Distance();
}

}  // namespace blink
