// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/animation/string_keyframe.h"

#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/heap/heap.h"

namespace blink {

namespace {

// Returns handle for the given CSSProperty.
// |value| is required only for custom properties.
PropertyHandle ToPropertyHandle(const CSSProperty& property,
                                const CSSValue* value) {
  if (property.IDEquals(CSSPropertyID::kVariable)) {
    return PropertyHandle(To<CSSCustomPropertyDeclaration>(*value).GetName());
  } else {
    return PropertyHandle(property, false);
  }
}

bool IsLogicalProperty(CSSPropertyID property_id) {
  const CSSProperty& property = CSSProperty::Get(property_id);
  const CSSProperty& resolved_property = property.ResolveDirectionAwareProperty(
      TextDirection::kLtr, WritingMode::kHorizontalTb);
  return resolved_property.PropertyID() != property_id;
}

MutableCSSPropertyValueSet* CreateCssPropertyValueSet() {
  return MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);
}

}  // namespace

using PropertyResolver = StringKeyframe::PropertyResolver;

StringKeyframe::StringKeyframe(const StringKeyframe& copy_from)
    : Keyframe(copy_from.offset_, copy_from.composite_, copy_from.easing_),
      input_properties_(copy_from.input_properties_),
      presentation_attribute_map_(
          copy_from.presentation_attribute_map_->MutableCopy()),
      svg_attribute_map_(copy_from.svg_attribute_map_),
      has_logical_property_(copy_from.has_logical_property_),
      text_direction_(copy_from.text_direction_),
      writing_mode_(copy_from.writing_mode_) {
  if (copy_from.css_property_map_)
    css_property_map_ = copy_from.css_property_map_->MutableCopy();
}

MutableCSSPropertyValueSet::SetResult StringKeyframe::SetCSSPropertyValue(
    const AtomicString& custom_property_name,
    const String& value,
    SecureContextMode secure_context_mode,
    StyleSheetContents* style_sheet_contents) {
  bool is_animation_tainted = true;

  auto* property_map = CreateCssPropertyValueSet();
  MutableCSSPropertyValueSet::SetResult result = property_map->SetProperty(
      custom_property_name, value, false, secure_context_mode,
      style_sheet_contents, is_animation_tainted);

  const CSSValue* parsed_value =
      property_map->GetPropertyCSSValue(custom_property_name);

  if (result.did_parse && parsed_value) {
    // Per specification we only keep properties around which are parsable.
    input_properties_.Set(PropertyHandle(custom_property_name),
                          MakeGarbageCollected<PropertyResolver>(
                              CSSPropertyID::kVariable, *parsed_value));
  }

  return result;
}

MutableCSSPropertyValueSet::SetResult StringKeyframe::SetCSSPropertyValue(
    CSSPropertyID property_id,
    const String& value,
    SecureContextMode secure_context_mode,
    StyleSheetContents* style_sheet_contents) {
  DCHECK_NE(property_id, CSSPropertyID::kInvalid);
  DCHECK_NE(property_id, CSSPropertyID::kVariable);
  const CSSProperty& property = CSSProperty::Get(property_id);

  if (CSSAnimations::IsAnimationAffectingProperty(property)) {
    bool did_parse = true;
    bool did_change = false;
    return MutableCSSPropertyValueSet::SetResult{did_parse, did_change};
  }

  auto* property_value_set = CreateCssPropertyValueSet();
  MutableCSSPropertyValueSet::SetResult result =
      property_value_set->SetProperty(
          property_id, value, false, secure_context_mode, style_sheet_contents);

  // TODO(crbug.com/1132078): Add flag to CSSProperty to track if it is for a
  // logical style.
  bool is_logical = false;
  if (property.IsShorthand()) {
    // Logical shorthands to not directly map to physical shorthands. Determine
    // if the shorthand is for a logical property by checking the first
    // longhand.
    if (property_value_set->PropertyCount()) {
      CSSPropertyValueSet::PropertyReference reference =
          property_value_set->PropertyAt(0);
      if (IsLogicalProperty(reference.Id()))
        is_logical = true;
    }
  } else {
    is_logical = IsLogicalProperty(property_id);
  }
  if (is_logical)
    has_logical_property_ = true;

  if (result.did_parse) {
    // Per specification we only keep properties around which are parsable.
    auto* resolver = MakeGarbageCollected<PropertyResolver>(
        property, property_value_set, is_logical);
    if (resolver->IsValid()) {
      input_properties_.Set(PropertyHandle(property), resolver);
      InvalidateCssPropertyMap();
    }
  }

  return result;
}

void StringKeyframe::SetCSSPropertyValue(const CSSProperty& property,
                                         const CSSValue& value) {
  CSSPropertyID property_id = property.PropertyID();
  DCHECK_NE(property_id, CSSPropertyID::kInvalid);
  DCHECK(!CSSAnimations::IsAnimationAffectingProperty(property));
  DCHECK(!property.IsShorthand());
  DCHECK(!IsLogicalProperty(property_id));
  input_properties_.Set(
      ToPropertyHandle(property, &value),
      MakeGarbageCollected<PropertyResolver>(property_id, value));
  InvalidateCssPropertyMap();
}

void StringKeyframe::RemoveCustomCSSProperty(const PropertyHandle& property) {
  DCHECK(property.IsCSSCustomProperty());
  if (css_property_map_)
    css_property_map_->RemoveProperty(property.CustomPropertyName());
  input_properties_.erase(property);
}

void StringKeyframe::SetPresentationAttributeValue(
    const CSSProperty& property,
    const String& value,
    SecureContextMode secure_context_mode,
    StyleSheetContents* style_sheet_contents) {
  DCHECK_NE(property.PropertyID(), CSSPropertyID::kInvalid);
  if (!CSSAnimations::IsAnimationAffectingProperty(property)) {
    presentation_attribute_map_->SetProperty(property.PropertyID(), value,
                                             false, secure_context_mode,
                                             style_sheet_contents);
  }
}

void StringKeyframe::SetSVGAttributeValue(const QualifiedName& attribute_name,
                                          const String& value) {
  svg_attribute_map_.Set(&attribute_name, value);
}

PropertyHandleSet StringKeyframe::Properties() const {
  // This is not used in time-critical code, so we probably don't need to
  // worry about caching this result.
  EnsureCssPropertyMap();
  PropertyHandleSet properties;
  for (unsigned i = 0; i < css_property_map_->PropertyCount(); ++i) {
    CSSPropertyValueSet::PropertyReference property_reference =
        css_property_map_->PropertyAt(i);
    // TODO(crbug.com/980160): Remove access to static Variable instance.
    const CSSProperty& property = CSSProperty::Get(property_reference.Id());
    DCHECK(!property.IsShorthand())
        << "Web Animations: Encountered unexpanded shorthand CSS property ("
        << static_cast<int>(property.PropertyID()) << ").";
    properties.insert(ToPropertyHandle(property, &property_reference.Value()));
  }

  for (unsigned i = 0; i < presentation_attribute_map_->PropertyCount(); ++i) {
    properties.insert(PropertyHandle(
        CSSProperty::Get(presentation_attribute_map_->PropertyAt(i).Id()),
        true));
  }

  for (auto* const key : svg_attribute_map_.Keys())
    properties.insert(PropertyHandle(*key));

  return properties;
}

bool StringKeyframe::HasCssProperty() const {
  PropertyHandleSet properties = Properties();
  for (const PropertyHandle& property : properties) {
    if (property.IsCSSProperty())
      return true;
  }
  return false;
}

void StringKeyframe::AddKeyframePropertiesToV8Object(
    V8ObjectBuilder& object_builder,
    Element* element) const {
  Keyframe::AddKeyframePropertiesToV8Object(object_builder, element);
  for (const auto& entry : input_properties_) {
    const PropertyHandle& property_handle = entry.key;
    const CSSValue* property_value = entry.value->CssValue();
    String property_name =
        AnimationInputHelpers::PropertyHandleToKeyframeAttribute(
            property_handle);

    object_builder.Add(property_name, property_value->CssText());
  }

  // Legacy code path for SVG and Presentation attributes.
  //
  // TODO(816956): Move these to input_properties_ and remove this. Note that
  // this code path is not well tested given that removing it didn't cause any
  // test failures.
  for (const PropertyHandle& property : Properties()) {
    if (property.IsCSSProperty())
      continue;

    String property_name =
        AnimationInputHelpers::PropertyHandleToKeyframeAttribute(property);
    String property_value;
    if (property.IsPresentationAttribute()) {
      const auto& attribute = property.PresentationAttribute();
      property_value = PresentationAttributeValue(attribute).CssText();
    } else {
      DCHECK(property.IsSVGAttribute());
      property_value = SvgPropertyValue(property.SvgAttribute());
    }
    object_builder.Add(property_name, property_value);
  }
}

void StringKeyframe::Trace(Visitor* visitor) const {
  visitor->Trace(input_properties_);
  visitor->Trace(css_property_map_);
  visitor->Trace(presentation_attribute_map_);
  Keyframe::Trace(visitor);
}

Keyframe* StringKeyframe::Clone() const {
  return MakeGarbageCollected<StringKeyframe>(*this);
}

bool StringKeyframe::SetLogicalPropertyResolutionContext(
    TextDirection text_direction,
    WritingMode writing_mode) {
  if (text_direction != text_direction_ || writing_mode != writing_mode_) {
    text_direction_ = text_direction;
    writing_mode_ = writing_mode;
    if (has_logical_property_) {
      // force a rebuild of the property map on the next property fetch.
      InvalidateCssPropertyMap();
      return true;
    }
  }
  return false;
}

void StringKeyframe::EnsureCssPropertyMap() const {
  if (css_property_map_)
    return;

  css_property_map_ =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);

  bool requires_sorting = false;
  HeapVector<Member<PropertyResolver>> resolvers;
  for (const auto& entry : input_properties_) {
    const PropertyHandle& property_handle = entry.key;
    if (!property_handle.IsCSSProperty())
      continue;

    if (property_handle.IsCSSCustomProperty()) {
      CSSPropertyName property_name(property_handle.CustomPropertyName());
      const CSSValue* value = entry.value->CssValue();
      css_property_map_->SetProperty(CSSPropertyValue(property_name, *value));
    } else {
      PropertyResolver* resolver = entry.value;
      if (resolver->IsLogical() || resolver->IsShorthand())
        requires_sorting = true;
      resolvers.push_back(resolver);
    }
  }

  if (requires_sorting) {
    std::stable_sort(resolvers.begin(), resolvers.end(),
                     PropertyResolver::HasLowerPriority);
  }

  for (const auto& resolver : resolvers) {
    resolver->AppendTo(css_property_map_, text_direction_, writing_mode_);
  }
}

Keyframe::PropertySpecificKeyframe*
StringKeyframe::CreatePropertySpecificKeyframe(
    const PropertyHandle& property,
    EffectModel::CompositeOperation effect_composite,
    double offset) const {
  EffectModel::CompositeOperation composite =
      composite_.value_or(effect_composite);
  if (property.IsCSSProperty()) {
    return MakeGarbageCollected<CSSPropertySpecificKeyframe>(
        offset, &Easing(), &CssPropertyValue(property), composite);
  }

  if (property.IsPresentationAttribute()) {
    return MakeGarbageCollected<CSSPropertySpecificKeyframe>(
        offset, &Easing(),
        &PresentationAttributeValue(property.PresentationAttribute()),
        composite);
  }

  DCHECK(property.IsSVGAttribute());
  return MakeGarbageCollected<SVGPropertySpecificKeyframe>(
      offset, &Easing(), SvgPropertyValue(property.SvgAttribute()), composite);
}

bool StringKeyframe::CSSPropertySpecificKeyframe::
    PopulateCompositorKeyframeValue(const PropertyHandle& property,
                                    Element& element,
                                    const ComputedStyle& base_style,
                                    const ComputedStyle* parent_style) const {
  compositor_keyframe_value_cache_ =
      StyleResolver::CreateCompositorKeyframeValueSnapshot(
          element, base_style, parent_style, property, value_.Get(), offset_);
  return true;
}

bool StringKeyframe::CSSPropertySpecificKeyframe::IsRevert() const {
  return value_ && value_->IsRevertValue();
}

Keyframe::PropertySpecificKeyframe*
StringKeyframe::CSSPropertySpecificKeyframe::NeutralKeyframe(
    double offset,
    scoped_refptr<TimingFunction> easing) const {
  return MakeGarbageCollected<CSSPropertySpecificKeyframe>(
      offset, std::move(easing), nullptr, EffectModel::kCompositeAdd);
}

void StringKeyframe::CSSPropertySpecificKeyframe::Trace(
    Visitor* visitor) const {
  visitor->Trace(value_);
  visitor->Trace(compositor_keyframe_value_cache_);
  Keyframe::PropertySpecificKeyframe::Trace(visitor);
}

Keyframe::PropertySpecificKeyframe*
StringKeyframe::CSSPropertySpecificKeyframe::CloneWithOffset(
    double offset) const {
  auto* clone = MakeGarbageCollected<CSSPropertySpecificKeyframe>(
      offset, easing_, value_.Get(), composite_);
  clone->compositor_keyframe_value_cache_ = compositor_keyframe_value_cache_;
  return clone;
}

Keyframe::PropertySpecificKeyframe*
SVGPropertySpecificKeyframe::CloneWithOffset(double offset) const {
  return MakeGarbageCollected<SVGPropertySpecificKeyframe>(offset, easing_,
                                                           value_, composite_);
}

Keyframe::PropertySpecificKeyframe*
SVGPropertySpecificKeyframe::NeutralKeyframe(
    double offset,
    scoped_refptr<TimingFunction> easing) const {
  return MakeGarbageCollected<SVGPropertySpecificKeyframe>(
      offset, std::move(easing), String(), EffectModel::kCompositeAdd);
}

// ----- Property Resolver -----

PropertyResolver::PropertyResolver(CSSPropertyID property_id,
                                   const CSSValue& css_value)
    : property_id_(property_id), css_value_(css_value) {}

PropertyResolver::PropertyResolver(
    const CSSProperty& property,
    const MutableCSSPropertyValueSet* property_value_set,
    bool is_logical)
    : property_id_(property.PropertyID()), is_logical_(is_logical) {
  DCHECK_NE(property_id_, CSSPropertyID::kInvalid);
  DCHECK_NE(property_id_, CSSPropertyID::kVariable);
  if (!property.IsShorthand())
    css_value_ = property_value_set->GetPropertyCSSValue(property_id_);
  else
    css_property_value_set_ = property_value_set->ImmutableCopyIfNeeded();
}

bool PropertyResolver::IsValid() const {
  return css_value_ || css_property_value_set_;
}

const CSSValue* PropertyResolver::CssValue() {
  DCHECK(IsValid());

  if (css_value_)
    return css_value_;

  // For shorthands create a special wrapper value, |CSSKeyframeShorthandValue|,
  // which can be used to correctly serialize it given longhands that are
  // present in this set.
  css_value_ = MakeGarbageCollected<CSSKeyframeShorthandValue>(
      property_id_, css_property_value_set_);
  return css_value_;
}

void PropertyResolver::AppendTo(MutableCSSPropertyValueSet* property_value_set,
                                TextDirection text_direction,
                                WritingMode writing_mode) {
  DCHECK(property_id_ != CSSPropertyID::kInvalid);
  DCHECK(property_id_ != CSSPropertyID::kVariable);

  if (css_property_value_set_) {
    // Shorthand property. Extract longhands from css_property_value_set_.
    if (is_logical_) {
      // Walk set of properties converting each property name to its
      // corresponding physical property.
      for (unsigned i = 0; i < css_property_value_set_->PropertyCount(); i++) {
        CSSPropertyValueSet::PropertyReference reference =
            css_property_value_set_->PropertyAt(i);
        SetProperty(property_value_set, reference.Id(), reference.Value(),
                    text_direction, writing_mode);
      }
    } else {
      property_value_set->MergeAndOverrideOnConflict(css_property_value_set_);
    }
  } else {
    SetProperty(property_value_set, property_id_, *css_value_, text_direction,
                writing_mode);
  }
}

void PropertyResolver::SetProperty(
    MutableCSSPropertyValueSet* property_value_set,
    CSSPropertyID property_id,
    const CSSValue& value,
    TextDirection text_direction,
    WritingMode writing_mode) {
  const CSSProperty& physical_property =
      CSSProperty::Get(property_id)
          .ResolveDirectionAwareProperty(text_direction, writing_mode);
  property_value_set->SetProperty(physical_property.PropertyID(), value);
}

void PropertyResolver::Trace(Visitor* visitor) const {
  visitor->Trace(css_value_);
  visitor->Trace(css_property_value_set_);
}

// static
bool PropertyResolver::HasLowerPriority(PropertyResolver* first,
                                        PropertyResolver* second) {
  // Longhand properties take precedence over shorthand properties.
  if (first->IsShorthand() != second->IsShorthand())
    return first->IsShorthand();

  // Physical properties take precedence over logical properties.
  if (first->IsLogical() != second->IsLogical())
    return first->IsLogical();

  // Two shorthands with overlapping longhand properties are sorted based
  // on the number of longhand properties in their expansions.
  if (first->IsShorthand())
    return first->ExpansionCount() > second->ExpansionCount();

  return false;
}

}  // namespace blink
