// Copyright 2016 Google Inc. 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_declared_style_declaration.h"

#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "cobalt/cssom/css_declared_style_data.h"
#include "cobalt/cssom/css_parser.h"
#include "cobalt/cssom/mutation_observer.h"

namespace cobalt {
namespace cssom {

namespace {

struct NonTrivialStaticFields {
  NonTrivialStaticFields()
      : location(base::SourceLocation(
            CSSStyleDeclaration::GetSourceLocationName(), 1, 1)) {}

  const base::SourceLocation location;

 private:
  DISALLOW_COPY_AND_ASSIGN(NonTrivialStaticFields);
};

// |non_trivial_static_fields| will be lazily created on the first time it's
// accessed.
base::LazyInstance<NonTrivialStaticFields> non_trivial_static_fields =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace

CSSDeclaredStyleDeclaration::CSSDeclaredStyleDeclaration(CSSParser* css_parser)
    : css_parser_(css_parser), mutation_observer_(NULL) {}

CSSDeclaredStyleDeclaration::CSSDeclaredStyleDeclaration(
    const scoped_refptr<CSSDeclaredStyleData>& data, CSSParser* css_parser)
    : data_(data), css_parser_(css_parser), mutation_observer_(NULL) {
  DCHECK(data_.get());
}

// This returns the result of serializing a CSS declaration block.
// The current implementation does not handle shorthands.
//   https://www.w3.org/TR/cssom/#serialize-a-css-declaration-block
std::string CSSDeclaredStyleDeclaration::css_text(
    script::ExceptionState* /*exception_state*/) const {
  return data_ ? data_->SerializeCSSDeclarationBlock() : std::string();
}

void CSSDeclaredStyleDeclaration::set_css_text(
    const std::string& css_text, script::ExceptionState* /*exception_state*/) {
  TRACE_EVENT0("cobalt::cssom", "CSSDeclaredStyleDeclaration::set_css_text");
  DCHECK(css_parser_);
  scoped_refptr<CSSDeclaredStyleData> declaration =
      css_parser_->ParseStyleDeclarationList(
          css_text, non_trivial_static_fields.Get().location);

  bool changed = true;

  if (declaration) {
    if (data_ && *data_ == *declaration) {
      changed = false;
    }
    data_ = declaration;
  } else {
    if (!data_) {
      changed = false;
    }
    data_ = NULL;
  }

  if (changed) {
    RecordMutation();
  }
}

// The length attribute must return the number of CSS declarations in the
// declarations.
//   https://www.w3.org/TR/cssom/#dom-cssstyledeclaration-length
unsigned int CSSDeclaredStyleDeclaration::length() const {
  return data_ ? data_->length() : 0;
}

// The item(index) method must return the property name of the CSS declaration
// at position index.
//   https://www.w3.org/TR/cssom/#dom-cssstyledeclaration-item
base::optional<std::string> CSSDeclaredStyleDeclaration::Item(
    unsigned int index) const {
  const char* item = data_ ? data_->Item(index) : NULL;
  return item ? base::optional<std::string>(item) : base::nullopt;
}

std::string CSSDeclaredStyleDeclaration::GetDeclaredPropertyValueStringByKey(
    const PropertyKey key) const {
  if (key > kMaxLonghandPropertyKey) {
    // Shorthand properties are never directly stored as declared properties,
    // but are expanded into their longhand property components during parsing.
    // TODO: Implement serialization of css values, see
    // https://www.w3.org/TR/cssom-1/#serializing-css-values
    DCHECK_LE(key, kMaxEveryPropertyKey);
    NOTIMPLEMENTED();
    DLOG(WARNING) << "Unsupported property query for \"" << GetPropertyName(key)
                  << "\": Returning of property value strings is not "
                     "supported for shorthand properties.";
    return std::string();
  }
  return (data_ && key != kNoneProperty) ? data_->GetPropertyValueString(key)
                                         : std::string();
}

void CSSDeclaredStyleDeclaration::SetPropertyValue(
    const std::string& property_name, const std::string& property_value,
    script::ExceptionState* /*exception_state*/) {
  DCHECK(css_parser_);
  if (!data_) {
    data_ = new CSSDeclaredStyleData();
  }
  css_parser_->ParsePropertyIntoDeclarationData(
      property_name, property_value, non_trivial_static_fields.Get().location,
      data_.get());

  RecordMutation();
}

void CSSDeclaredStyleDeclaration::SetProperty(
    const std::string& property_name, const std::string& property_value,
    const std::string& priority, script::ExceptionState* /*exception_state*/) {
  DLOG(INFO) << "CSSDeclaredStyleDeclaration::SetProperty(" << property_name
             << "," << property_value << "," << priority << ")";
  DCHECK(css_parser_);
  if (!data_) {
    data_ = new CSSDeclaredStyleData();
  }
  css_parser_->ParsePropertyIntoDeclarationData(
      property_name, property_value, non_trivial_static_fields.Get().location,
      data_.get());

  RecordMutation();
}

void CSSDeclaredStyleDeclaration::RecordMutation() {
  if (mutation_observer_) {
    // Trigger layout update.
    mutation_observer_->OnCSSMutation();
  }
}

void CSSDeclaredStyleDeclaration::AssignFrom(
    const CSSDeclaredStyleDeclaration& rhs) {
  if (!rhs.data_) {
    data_ = NULL;
    return;
  }
  if (!data_) {
    data_ = new CSSDeclaredStyleData();
  }
  data_->AssignFrom(*rhs.data_);
}

}  // namespace cssom
}  // namespace cobalt
