// Copyright 2020 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/css/resolver/cascade_expansion.h"

#include "third_party/blink/renderer/core/css/resolver/match_result.h"
#include "third_party/blink/renderer/core/css/rule_set.h"

namespace blink {

namespace {

CascadeFilter AddValidPropertiesFilter(
    CascadeFilter filter,
    const MatchedProperties& matched_properties) {
  switch (static_cast<ValidPropertyFilter>(
      matched_properties.types_.valid_property_filter)) {
    case ValidPropertyFilter::kNoFilter:
      return filter;
    case ValidPropertyFilter::kCue:
      return filter.Add(CSSProperty::kValidForCue, false);
    case ValidPropertyFilter::kFirstLetter:
      return filter.Add(CSSProperty::kValidForFirstLetter, false);
    case ValidPropertyFilter::kMarker:
      return filter.Add(CSSProperty::kValidForMarker, false);
    case ValidPropertyFilter::kHighlight:
      return filter.Add(CSSProperty::kValidForHighlight, false);
  }
}

CascadeFilter AddLinkFilter(CascadeFilter filter,
                            const MatchedProperties& matched_properties) {
  switch (matched_properties.types_.link_match_type) {
    case CSSSelector::kMatchVisited:
      return filter.Add(CSSProperty::kVisited, false);
    case CSSSelector::kMatchLink:
      return filter.Add(CSSProperty::kVisited, true);
    case CSSSelector::kMatchAll:
      return filter;
    default:
      return filter.Add(CSSProperty::kProperty, true);
  }
}

CascadeFilter AmendFilter(CascadeFilter filter,
                          const MatchedProperties& matched_properties) {
  return AddLinkFilter(AddValidPropertiesFilter(filter, matched_properties),
                       matched_properties);
}

}  // anonymous namespace

CascadeExpansion::CascadeExpansion(const MatchedProperties& matched_properties,
                                   const Document& document,
                                   CascadeFilter filter,
                                   size_t matched_properties_index)
    : document_(document),
      matched_properties_(matched_properties),
      size_(matched_properties.properties->PropertyCount()),
      filter_(AmendFilter(filter, matched_properties)),
      matched_properties_index_(matched_properties_index) {
  // We can't handle a MatchResult with more than 0xFFFF MatchedProperties,
  // or a MatchedProperties object with more than 0xFFFF declarations. If this
  // happens, we skip right to the end, and emit nothing.
  if (size_ > kMaxDeclarationIndex + 1 ||
      matched_properties_index_ > kMaxMatchedPropertiesIndex) {
    index_ = size_;
  } else {
    Next();
  }
}

CascadeExpansion::CascadeExpansion(const CascadeExpansion& o)
    : document_(o.document_),
      state_(o.state_),
      matched_properties_(o.matched_properties_),
      priority_(o.priority_),
      index_(o.index_),
      size_(o.size_),
      filter_(o.filter_),
      matched_properties_index_(o.matched_properties_index_),
      id_(o.id_),
      property_(id_ == CSSPropertyID::kVariable ? &custom_ : o.property_),
      custom_(o.custom_) {}

void CascadeExpansion::Next() {
  do {
    switch (state_) {
      case State::kInit:
        AdvanceNormal();
        break;
      case State::kNormal:
        if (ShouldEmitVisited() && AdvanceVisited())
          break;
        AdvanceNormal();
        break;
      case State::kVisited:
        AdvanceNormal();
        break;
      case State::kAll:
        AdvanceAll();
        break;
    }
  } while (!AtEnd() && filter_.Rejects(*property_));
}

bool CascadeExpansion::IsAffectedByAll(CSSPropertyID id) {
  const CSSProperty& property = CSSProperty::Get(id);
  return !property.IsShorthand() && property.IsAffectedByAll();
}

bool CascadeExpansion::ShouldEmitVisited() const {
  // This check is slightly redundant, as the emitted property would anyway
  // be skipped by the do-while in Next(). However, it's probably good to avoid
  // entering State::kVisited at all, if we can avoid it.
  return !filter_.Rejects(CSSProperty::kVisited, true);
}

void CascadeExpansion::AdvanceNormal() {
  state_ = State::kNormal;
  ++index_;
  if (AtEnd())
    return;
  auto reference = PropertyAt(index_);
  const auto& metadata = reference.PropertyMetadata();
  id_ = metadata.PropertyID();
  priority_ = CascadePriority(
      matched_properties_.types_.origin, metadata.important_,
      matched_properties_.types_.tree_order,
      EncodeMatchResultPosition(matched_properties_index_, index_));

  switch (id_) {
    case CSSPropertyID::kVariable:
      custom_ = CustomProperty(reference.Name().ToAtomicString(), document_);
      property_ = &custom_;
      break;
    case CSSPropertyID::kAll:
      state_ = State::kAll;
      id_ = kFirstCSSProperty;
      property_ = &CSSProperty::Get(id_);
      // If this DCHECK is triggered, it means firstCSSProperty is not affected
      // by 'all', and we need a function for figuring out the first property
      // that _is_ affected by 'all'.
      DCHECK(IsAffectedByAll(id_));
      break;
    default:
      property_ = &CSSProperty::Get(id_);
      break;
  }

  DCHECK(property_);
}

bool CascadeExpansion::AdvanceVisited() {
  DCHECK(ShouldEmitVisited());
  DCHECK(property_);
  const CSSProperty* visited = property_->GetVisitedProperty();
  if (!visited)
    return false;
  property_ = visited;
  id_ = visited->PropertyID();
  state_ = State::kVisited;
  return true;
}

void CascadeExpansion::AdvanceAll() {
  state_ = State::kAll;

  int i = static_cast<int>(id_) + 1;
  int end = kIntLastCSSProperty + 1;

  for (; i < end; ++i) {
    id_ = ConvertToCSSPropertyID(i);
    if (IsAffectedByAll(id_))
      break;
  }

  if (i >= end)
    AdvanceNormal();
  else
    property_ = &CSSProperty::Get(id_);
}

CSSPropertyValueSet::PropertyReference CascadeExpansion::PropertyAt(
    size_t index) const {
  DCHECK(!AtEnd());
  return matched_properties_.properties->PropertyAt(index_);
}

uint16_t CascadeExpansion::TreeOrder() const {
  return matched_properties_.types_.tree_order;
}

}  // namespace blink
