// Copyright 2016 The Cobalt Authors. 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/css_computed_style_data.h"

#include <limits>

#include "base/lazy_instance.h"
#include "base/strings/string_util.h"
#include "cobalt/cssom/css_computed_style_declaration.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/length_value.h"

namespace cobalt {
namespace cssom {

CSSComputedStyleData::PropertySetMatcher::PropertySetMatcher(
    const PropertyKeyVector& properties)
    : properties_(properties) {
  for (size_t i = 0; i < properties_.size(); ++i) {
    PropertyKey property_key = properties_[i];
    DCHECK_GT(property_key, kNoneProperty);
    DCHECK_LE(property_key, kMaxLonghandPropertyKey);
    properties_bitset_.set(property_key);
  }
}

bool CSSComputedStyleData::PropertySetMatcher::DoDeclaredPropertiesMatch(
    const scoped_refptr<const CSSComputedStyleData>& lhs,
    const scoped_refptr<const CSSComputedStyleData>& rhs) const {
  LonghandPropertiesBitset lhs_properties_bitset =
      lhs->declared_properties_ & properties_bitset_;
  LonghandPropertiesBitset rhs_properties_bitset =
      rhs->declared_properties_ & properties_bitset_;
  if (lhs_properties_bitset != rhs_properties_bitset) {
    return false;
  } else if (lhs_properties_bitset.none()) {
    return true;
  }
  for (size_t i = 0; i < properties_.size(); ++i) {
    PropertyKey property_key = properties_[i];
    if (lhs_properties_bitset[property_key] &&
        !lhs->declared_property_values_.find(property_key)
             ->second->Equals(
                 *rhs->declared_property_values_.find(property_key)->second)) {
      return false;
    }
  }
  return true;
}

CSSComputedStyleData::CSSComputedStyleData() {}
CSSComputedStyleData::~CSSComputedStyleData() {}

const scoped_refptr<PropertyValue>&
CSSComputedStyleData::GetPropertyValueReference(PropertyKey key) const {
  DCHECK_GT(key, kNoneProperty);
  DCHECK_LE(key, kMaxLonghandPropertyKey);

  // If the property's value is explicitly declared, then simply return it.
  if (declared_properties_[key]) {
    return declared_property_values_.find(key)->second;
  }

  // Otherwise, if the property is inherited and the parent has inherited
  // properties, then retrieve the parent's value for the property.
  if (parent_computed_style_declaration_ &&
      GetPropertyInheritance(key) == kInheritedYes &&
      parent_computed_style_declaration_->HasInheritedProperties()) {
    return parent_computed_style_declaration_
        ->GetInheritedPropertyValueReference(key);
  }

  // For the root element, which has no parent element, the inherited value is
  // the initial value of the property.
  //   https://www.w3.org/TR/css-cascade-3/#inheriting
  return GetComputedInitialValue(key);
}

scoped_refptr<PropertyValue>&
CSSComputedStyleData::GetDeclaredPropertyValueReference(PropertyKey key) {
  DCHECK_GT(key, kNoneProperty);
  DCHECK_LE(key, kMaxLonghandPropertyKey);
  DCHECK(declared_properties_[key]);
  return declared_property_values_.find(key)->second;
}

namespace {
struct NonTrivialStaticFields {
  NonTrivialStaticFields()
      : zero_length_value(new LengthValue(0.0f, kPixelsUnit)) {}

  const scoped_refptr<PropertyValue> zero_length_value;

 private:
  DISALLOW_COPY_AND_ASSIGN(NonTrivialStaticFields);
};

base::LazyInstance<NonTrivialStaticFields>::DestructorAtExit
    non_trivial_static_fields = LAZY_INSTANCE_INITIALIZER;
}  // namespace

const scoped_refptr<PropertyValue>&
CSSComputedStyleData::GetComputedInitialValue(PropertyKey key) const {
  switch (key) {
    case kBorderTopColorProperty:
    case kBorderRightColorProperty:
    case kBorderBottomColorProperty:
    case kBorderLeftColorProperty:
    case kOutlineColorProperty:
    case kTextDecorationColorProperty:
      // Note that border color and text decoration color are not inherited.
      // The initial value of border color is 'currentColor' which means the
      // border color is the same as the value of the 'color' property.
      //    https://www.w3.org/TR/css3-color/#currentcolor
      return color();

    case kBorderTopWidthProperty:
    case kBorderRightWidthProperty:
    case kBorderBottomWidthProperty:
    case kBorderLeftWidthProperty:
    case kOutlineWidthProperty:
      // If the border style is 'none' or 'hidden', border width would be 0.
      //   https://www.w3.org/TR/css3-background/#border-width
      if (IsBorderStyleNoneOrHiddenForAnEdge(key)) {
        return non_trivial_static_fields.Get().zero_length_value;
      }
      break;

    case kAllProperty:
    case kAlignContentProperty:
    case kAlignItemsProperty:
    case kAlignSelfProperty:
    case kAnimationDelayProperty:
    case kAnimationDirectionProperty:
    case kAnimationDurationProperty:
    case kAnimationFillModeProperty:
    case kAnimationIterationCountProperty:
    case kAnimationNameProperty:
    case kAnimationProperty:
    case kAnimationTimingFunctionProperty:
    case kBackgroundColorProperty:
    case kBackgroundImageProperty:
    case kBackgroundPositionProperty:
    case kBackgroundProperty:
    case kBackgroundRepeatProperty:
    case kBackgroundSizeProperty:
    case kBorderBottomLeftRadiusProperty:
    case kBorderBottomProperty:
    case kBorderBottomRightRadiusProperty:
    case kBorderBottomStyleProperty:
    case kBorderColorProperty:
    case kBorderLeftProperty:
    case kBorderLeftStyleProperty:
    case kBorderProperty:
    case kBorderRadiusProperty:
    case kBorderRightProperty:
    case kBorderRightStyleProperty:
    case kBorderStyleProperty:
    case kBorderTopLeftRadiusProperty:
    case kBorderTopProperty:
    case kBorderTopRightRadiusProperty:
    case kBorderTopStyleProperty:
    case kBorderWidthProperty:
    case kBottomProperty:
    case kBoxShadowProperty:
    case kColorProperty:
    case kContentProperty:
    case kDisplayProperty:
    case kFilterProperty:
    case kFlexProperty:
    case kFlexBasisProperty:
    case kFlexDirectionProperty:
    case kFlexFlowProperty:
    case kFlexGrowProperty:
    case kFlexShrinkProperty:
    case kFlexWrapProperty:
    case kFontProperty:
    case kFontFamilyProperty:
    case kFontStyleProperty:
    case kFontWeightProperty:
    case kFontSizeProperty:
    case kHeightProperty:
    case kJustifyContentProperty:
    case kLeftProperty:
    case kLineHeightProperty:
    case kMarginBottomProperty:
    case kMarginLeftProperty:
    case kMarginProperty:
    case kMarginRightProperty:
    case kMarginTopProperty:
    case kMaxHeightProperty:
    case kMaxWidthProperty:
    case kMinHeightProperty:
    case kMinWidthProperty:
    case kNoneProperty:
    case kOpacityProperty:
    case kOrderProperty:
    case kOutlineProperty:
    case kOutlineStyleProperty:
    case kOverflowProperty:
    case kOverflowWrapProperty:
    case kPaddingBottomProperty:
    case kPaddingLeftProperty:
    case kPaddingProperty:
    case kPaddingRightProperty:
    case kPaddingTopProperty:
    case kPointerEventsProperty:
    case kPositionProperty:
    case kRightProperty:
    case kSrcProperty:
    case kTextAlignProperty:
    case kTextDecorationLineProperty:
    case kTextDecorationProperty:
    case kTextIndentProperty:
    case kTextOverflowProperty:
    case kTextShadowProperty:
    case kTextTransformProperty:
    case kTopProperty:
    case kTransformOriginProperty:
    case kTransformProperty:
    case kTransitionDelayProperty:
    case kTransitionDurationProperty:
    case kTransitionProperty:
    case kTransitionPropertyProperty:
    case kTransitionTimingFunctionProperty:
    case kUnicodeRangeProperty:
    case kVerticalAlignProperty:
    case kVisibilityProperty:
    case kWhiteSpaceProperty:
    case kWidthProperty:
    case kWordWrapProperty:
    case kZIndexProperty:
      break;
  }

  return GetPropertyInitialValue(key);
}

bool CSSComputedStyleData::IsBorderStyleNoneOrHiddenForAnEdge(
    PropertyKey key) const {
  scoped_refptr<PropertyValue> border_style;
  switch (key) {
    case kBorderTopWidthProperty:
      border_style = border_top_style();
      break;
    case kBorderRightWidthProperty:
      border_style = border_right_style();
      break;
    case kBorderBottomWidthProperty:
      border_style = border_bottom_style();
      break;
    case kBorderLeftWidthProperty:
      border_style = border_left_style();
      break;
    default:
      DCHECK_EQ(key, kOutlineWidthProperty);
      border_style = outline_style();
      break;
  }

  if (border_style == KeywordValue::GetNone() ||
      border_style == KeywordValue::GetHidden()) {
    return true;
  }

  return false;
}

void CSSComputedStyleData::SetPropertyValue(
    const PropertyKey key, const scoped_refptr<PropertyValue>& value) {
  DCHECK_GT(key, kNoneProperty);
  DCHECK_LE(key, kMaxLonghandPropertyKey);

  if (value) {
    declared_properties_.set(key, true);
    declared_property_values_[key] = value;
    // Only set |has_declared_inherited_properties_| if the property is
    // inherited and the the value isn't explicitly set to "inherit". If it is
    // set to "inherit", then the value is simply a copy of the parent's value,
    // which doesn't necessitate the node being included in the inheritance
    // tree, as it doesn't provide new information.
    // NOTE: Declaring a value of "inherit" on an inherited property is used for
    // transitions, which need to know the original value of the property (which
    // would otherwise be lost when the parent changed).
    has_declared_inherited_properties_ =
        has_declared_inherited_properties_ ||
        (GetPropertyInheritance(key) == kInheritedYes &&
         value != KeywordValue::GetInherit());
  } else if (declared_properties_[key]) {
    declared_properties_.set(key, false);
    declared_property_values_.erase(key);
  }
}

void CSSComputedStyleData::AssignFrom(const CSSComputedStyleData& rhs) {
  declared_properties_ = rhs.declared_properties_;
  declared_property_values_ = rhs.declared_property_values_;
  has_declared_inherited_properties_ = rhs.has_declared_inherited_properties_;
  declared_properties_inherited_from_parent_ =
      rhs.declared_properties_inherited_from_parent_;
  parent_computed_style_declaration_ = rhs.parent_computed_style_declaration_;
  is_inline_before_blockification_ = rhs.is_inline_before_blockification_;
}

std::string CSSComputedStyleData::SerializeCSSDeclarationBlock() const {
  // All longhand properties that are supported CSS properties, in
  // lexicographical order, with the value being the resolved value.
  //   https://www.w3.org/TR/2013/WD-cssom-20131205/#dom-window-getcomputedstyle

  // TODO: Return the resolved value instead of the computed value. See
  // https://www.w3.org/TR/2013/WD-cssom-20131205/#resolved-value.
  std::string serialized_text;
  for (size_t index = 0; index <= kMaxLonghandPropertyKey; ++index) {
    PropertyKey key = GetLexicographicalLonghandPropertyKey(index);
    if (!serialized_text.empty()) {
      serialized_text.push_back(' ');
    }
    serialized_text.append(GetPropertyName(key));
    serialized_text.append(": ");
    serialized_text.append(GetPropertyValue(key)->ToString());
    serialized_text.push_back(';');
  }
  return serialized_text;
}

void CSSComputedStyleData::AddDeclaredPropertyInheritedFromParent(
    PropertyKey key) {
  DCHECK_GT(key, kNoneProperty);
  DCHECK_LE(key, kMaxLonghandPropertyKey);
  declared_properties_inherited_from_parent_.push_back(key);
}

bool CSSComputedStyleData::AreDeclaredPropertiesInheritedFromParentValid()
    const {
  // If there are no declared properties inherited from the parent, then it's
  // impossible for them to be invalid.
  if (declared_properties_inherited_from_parent_.size() == 0) {
    return true;
  }

  if (!parent_computed_style_declaration_) {
    return false;
  }

  const scoped_refptr<const CSSComputedStyleData>& parent_computed_style_data =
      parent_computed_style_declaration_->data();
  if (!parent_computed_style_data) {
    return false;
  }

  // Verify that the parent's data is valid.
  DCHECK(parent_computed_style_data
             ->AreDeclaredPropertiesInheritedFromParentValid());

  // Walk the declared properties inherited from the parent. They're invalid if
  // any no longer match the parent's value.
  for (PropertyKeyVector::const_iterator iter =
           declared_properties_inherited_from_parent_.begin();
       iter != declared_properties_inherited_from_parent_.end(); ++iter) {
    if (!GetPropertyValueReference(*iter)->Equals(
            *parent_computed_style_data->GetPropertyValueReference(*iter))) {
      return false;
    }
  }
  return true;
}

bool CSSComputedStyleData::DoDeclaredPropertiesMatch(
    const scoped_refptr<const CSSComputedStyleData>& other) const {
  // If the bitsets don't match, then there's no need to check the values;
  // the declared properties are guaranteed to not match.
  if (declared_properties_ != other->declared_properties_) {
    return false;
  }

  // Verify that the same number of declared property values exist within the
  // two CSSComputedStyleData objects. This should be guaranteed by the
  // bitsets matching.
  DCHECK_EQ(declared_property_values_.size(),
            other->declared_property_values_.size());

  // Walk the two lists of declared property values looking for any keys or
  // values that don't match.
  PropertyValues::const_iterator iter1 = declared_property_values_.begin();
  PropertyValues::const_iterator iter2 =
      other->declared_property_values_.begin();
  for (; iter1 != declared_property_values_.end(); ++iter1, ++iter2) {
    if (iter1->first != iter2->first ||
        !iter1->second->Equals(*iter2->second)) {
      return false;
    }
  }

  return true;
}

void CSSComputedStyleData::SetParentComputedStyleDeclaration(
    const scoped_refptr<CSSComputedStyleDeclaration>&
        parent_computed_style_declaration) {
  parent_computed_style_declaration_ = parent_computed_style_declaration;
}

const scoped_refptr<CSSComputedStyleDeclaration>&
CSSComputedStyleData::GetParentComputedStyleDeclaration() const {
  return parent_computed_style_declaration_;
}

}  // namespace cssom
}  // namespace cobalt
