// 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.

#ifndef COBALT_CSSOM_CSS_DECLARED_STYLE_DECLARATION_H_
#define COBALT_CSSOM_CSS_DECLARED_STYLE_DECLARATION_H_

#include <string>

#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "cobalt/cssom/css_declared_style_data.h"
#include "cobalt/cssom/css_style_declaration.h"
#include "cobalt/script/exception_state.h"

namespace cobalt {
namespace cssom {

class CSSParser;

// A CSS declaration block is an ordered collection of CSS properties with their
// associated values, also named CSS declarations. In the DOM a CSS declaration
// block is a CSSStyleDeclaration object.
//   https://www.w3.org/TR/2013/WD-cssom-20131205/#css-declaration-blocks
// The CSSDeclaredStyleDeclaration implements a CSS Declaration block
// for declared styles, such as css style rules and inline styles.
class CSSDeclaredStyleDeclaration : public CSSStyleDeclaration {
 public:
  using CSSStyleDeclaration::SetProperty;

  explicit CSSDeclaredStyleDeclaration(CSSParser* css_parser);

  CSSDeclaredStyleDeclaration(const scoped_refptr<CSSDeclaredStyleData>& data,
                              CSSParser* css_parser);

  // From CSSStyleDeclaration.

  std::string css_text(script::ExceptionState* exception_state) const OVERRIDE;
  void set_css_text(const std::string& css_text,
                    script::ExceptionState* exception_state) OVERRIDE;

  unsigned int length() const OVERRIDE;

  base::optional<std::string> Item(unsigned int index) const OVERRIDE;

  void SetPropertyValue(const std::string& property_name,
                        const std::string& property_value,
                        script::ExceptionState* exception_state) OVERRIDE;

  void SetProperty(const std::string& property_name,
                   const std::string& property_value,
                   const std::string& priority,
                   script::ExceptionState* exception_state) OVERRIDE;

  // Custom.

  const scoped_refptr<CSSDeclaredStyleData>& data() const { return data_; }
  void set_mutation_observer(MutationObserver* observer) {
    mutation_observer_ = observer;
  }

  void AssignFrom(const CSSDeclaredStyleDeclaration& rhs);

 private:
  // From CSSStyleDeclaration.
  std::string GetDeclaredPropertyValueStringByKey(
      const PropertyKey key) const OVERRIDE;

  // Custom.
  void RecordMutation();

  scoped_refptr<CSSDeclaredStyleData> data_;

  CSSParser* const css_parser_;
  MutationObserver* mutation_observer_;

  DISALLOW_COPY_AND_ASSIGN(CSSDeclaredStyleDeclaration);
};

}  // namespace cssom
}  // namespace cobalt

#endif  // COBALT_CSSOM_CSS_DECLARED_STYLE_DECLARATION_H_
