// Copyright 2018 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/cssom/style_property_map_read_only_main_thread.h"

#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/property_registration.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"

namespace blink {

namespace {

class StylePropertyMapIterationSource final
    : public PairIterable<String, CSSStyleValueVector>::IterationSource {
 public:
  explicit StylePropertyMapIterationSource(
      HeapVector<StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry>
          values)
      : index_(0), values_(values) {}

  bool Next(ScriptState*,
            String& key,
            CSSStyleValueVector& value,
            ExceptionState&) override {
    if (index_ >= values_.size())
      return false;

    const StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry& pair =
        values_.at(index_++);
    key = pair.first;
    value = pair.second;
    return true;
  }

  void Trace(Visitor* visitor) const override {
    visitor->Trace(values_);
    PairIterable<String, CSSStyleValueVector>::IterationSource::Trace(visitor);
  }

 private:
  wtf_size_t index_;
  const HeapVector<StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry>
      values_;
};

}  // namespace

CSSStyleValue* StylePropertyMapReadOnlyMainThread::get(
    const ExecutionContext* execution_context,
    const String& property_name,
    ExceptionState& exception_state) const {
  base::Optional<CSSPropertyName> name =
      CSSPropertyName::From(execution_context, property_name);

  if (!name) {
    exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
    return nullptr;
  }

  const CSSProperty& property = CSSProperty::Get(name->Id());
  if (property.IsShorthand())
    return GetShorthandProperty(property);

  const CSSValue* value = (name->IsCustomProperty())
                              ? GetCustomProperty(name->ToAtomicString())
                              : GetProperty(name->Id());
  if (!value)
    return nullptr;

  // Custom properties count as repeated whenever we have a CSSValueList.
  if (property.IsRepeated() ||
      (name->IsCustomProperty() && value->IsValueList())) {
    CSSStyleValueVector values =
        StyleValueFactory::CssValueToStyleValueVector(*name, *value);
    return values.IsEmpty() ? nullptr : values[0];
  }

  return StyleValueFactory::CssValueToStyleValue(*name, *value);
}

CSSStyleValueVector StylePropertyMapReadOnlyMainThread::getAll(
    const ExecutionContext* execution_context,
    const String& property_name,
    ExceptionState& exception_state) const {
  base::Optional<CSSPropertyName> name =
      CSSPropertyName::From(execution_context, property_name);

  if (!name) {
    exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
    return CSSStyleValueVector();
  }

  const CSSProperty& property = CSSProperty::Get(name->Id());
  if (property.IsShorthand()) {
    CSSStyleValueVector values;
    if (CSSStyleValue* value = GetShorthandProperty(property))
      values.push_back(value);
    return values;
  }

  const CSSValue* value = (name->IsCustomProperty())
                              ? GetCustomProperty(name->ToAtomicString())
                              : GetProperty(name->Id());
  if (!value)
    return CSSStyleValueVector();

  return StyleValueFactory::CssValueToStyleValueVector(*name, *value);
}

bool StylePropertyMapReadOnlyMainThread::has(
    const ExecutionContext* execution_context,
    const String& property_name,
    ExceptionState& exception_state) const {
  return !getAll(execution_context, property_name, exception_state).IsEmpty();
}

StylePropertyMapReadOnlyMainThread::IterationSource*
StylePropertyMapReadOnlyMainThread::StartIteration(ScriptState* script_state,
                                                   ExceptionState&) {
  HeapVector<StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry> result;

  ForEachProperty([&result](const CSSPropertyName& name,
                            const CSSValue& value) {
    auto values = StyleValueFactory::CssValueToStyleValueVector(name, value);
    result.emplace_back(name.ToAtomicString(), std::move(values));
  });

  return MakeGarbageCollected<StylePropertyMapIterationSource>(result);
}

CSSStyleValue* StylePropertyMapReadOnlyMainThread::GetShorthandProperty(
    const CSSProperty& property) const {
  DCHECK(property.IsShorthand());
  const auto serialization = SerializationForShorthand(property);
  if (serialization.IsEmpty())
    return nullptr;
  return MakeGarbageCollected<CSSUnsupportedStyleValue>(
      CSSPropertyName(property.PropertyID()), serialization);
}

}  // namespace blink
