/*
 * Copyright 2014 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_DOM_ELEMENT_H_
#define COBALT_DOM_ELEMENT_H_

#include <string>

#include "base/containers/small_map.h"
#include "base/hash_tables.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/string_piece.h"
#include "cobalt/base/token.h"
#include "cobalt/dom/node.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/web_animations/animation_set.h"

namespace cobalt {
namespace dom {

class DOMRect;
class DOMRectList;
class DOMTokenList;
class HTMLCollection;
class HTMLElement;
class HTMLElementContext;
class NamedNodeMap;

// The Element interface represents an object of a Document. This interface
// describes methods and properties common to all kinds of elements.
//   https://www.w3.org/TR/2014/WD-dom-20140710/#interface-element
class Element : public Node {
 public:
  // NOTE1: The array size of base::SmallMap and the decision to use
  // base::hash_map as the underlying container type are based on extensive
  // performance testing. Do not change these unless additional profiling data
  // justifies it.
  // NOTE2: Using base::SmallMap rather than base::hash_map also results in
  // substantial memory gains when live videos are played. These videos trigger
  // the creation of XML documents with over 20k elements, of which over 99%
  // contain a single attribute. By using base::SmallMap, these single attribute
  // elements are contained within arrays rather than hash_maps.
  typedef base::SmallMap<base::hash_map<std::string, std::string>, 1>
      AttributeMap;

  explicit Element(Document* document);
  Element(Document* document, base::Token tag_name);

  // Web API: Node
  //
  base::Token node_name() const OVERRIDE { return tag_name(); }
  NodeType node_type() const OVERRIDE { return Node::kElementNode; }

  base::optional<std::string> text_content() const OVERRIDE;
  void set_text_content(
      const base::optional<std::string>& text_content) OVERRIDE;

  bool HasAttributes() const OVERRIDE;

  // Web API: Element
  //

  base::Token tag_name() const { return tag_name_; }

  base::Token id() const { return id_attribute_; }
  void set_id(const std::string& value) { SetAttribute("id", value); }

  std::string class_name() const { return GetAttribute("class").value_or(""); }
  void set_class_name(const std::string& value) {
    SetAttribute("class", value);
  }

  const scoped_refptr<DOMTokenList>& class_list();
  scoped_refptr<NamedNodeMap> attributes();

  base::optional<std::string> GetAttribute(const std::string& name) const;
  void SetAttribute(const std::string& name, const std::string& value);
  void RemoveAttribute(const std::string& name);
  bool HasAttribute(const std::string& name) const;

  scoped_refptr<HTMLCollection> GetElementsByTagName(
      const std::string& tag_name) const;
  scoped_refptr<HTMLCollection> GetElementsByClassName(
      const std::string& class_name) const;

  // Web API: CSSOM View Module: Extensions to the Element Interface (partial
  // interface)
  //   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#extensions-to-the-element-interface
  scoped_refptr<DOMRect> GetBoundingClientRect();
  virtual scoped_refptr<DOMRectList> GetClientRects();
  virtual float client_top();
  virtual float client_left();
  virtual float client_width();
  virtual float client_height();

  // Web API: DOM Parsing and Serialization (partial interface)
  //   https://www.w3.org/TR/DOM-Parsing/#extensions-to-the-element-interface
  //
  std::string inner_html() const;
  void set_inner_html(const std::string& inner_html);
  std::string outer_html(script::ExceptionState* exception_state) const;
  void set_outer_html(const std::string& outer_html,
                      script::ExceptionState* exception_state);

  // Custom, not in any spec: Node.
  //
  scoped_refptr<Element> AsElement() OVERRIDE { return this; }

  void Accept(NodeVisitor* visitor) OVERRIDE;
  void Accept(ConstNodeVisitor* visitor) const OVERRIDE;

  scoped_refptr<Node> Duplicate() const OVERRIDE;

  // Custom, not in any spec.
  //
  // Returns whether the element has no children at all except comments or
  // processing instructions.
  //   https://www.w3.org/TR/selectors4/#empty-pseudo
  bool IsEmpty();

  // Returns whether the element has focus.
  //   https://www.w3.org/TR/selectors4/#focus-pseudo
  bool HasFocus();

  // Returns a map that holds the actual attributes of the element.
  const AttributeMap& attribute_map() const { return attribute_map_; }

  // These are called when the element is generated by the parser, rather than
  // by javascript.
  // opening_tag_location points to ">" of opening tag.
  virtual void OnParserStartTag(
      const base::SourceLocation& opening_tag_location) {
    UNREFERENCED_PARAMETER(opening_tag_location);
  }
  virtual void OnParserEndTag() {}

  // Used to ensure that the style attribute value reflects the style
  // declaration.
  //   https://www.w3.org/TR/html5/dom.html#the-style-attribute
  virtual base::optional<std::string> GetStyleAttribute() const;
  virtual void SetStyleAttribute(const std::string& value);
  virtual void RemoveStyleAttribute();

  virtual scoped_refptr<HTMLElement> AsHTMLElement();

  const scoped_refptr<web_animations::AnimationSet>& animations() {
    return animations_;
  }

  DEFINE_WRAPPABLE_TYPE(Element);

 protected:
  ~Element() OVERRIDE;

  // Getting and setting boolean attribute.
  //   https://www.w3.org/TR/html5/infrastructure.html#boolean-attribute
  bool GetBooleanAttribute(const std::string& name) const;
  void SetBooleanAttribute(const std::string& name, bool value);

  void CopyAttributes(const Element& other);

  HTMLElementContext* html_element_context();

 private:
  // From EventTarget.
  std::string GetDebugName() OVERRIDE;

  virtual void OnSetAttribute(const std::string& /* name */,
                              const std::string& /* value */) {}
  virtual void OnRemoveAttribute(const std::string& /* name */) {}

  // Callback for error when parsing inner / outer HTML.
  void HTMLParseError(const std::string& error);

  // Tag name of the element.
  base::Token tag_name_;
  // A map that holds the actual element attributes.
  AttributeMap attribute_map_;
  // The "id" attribute for this element. Stored here in addition to being
  // stored in |attribute_map_| as an optimization for id().
  base::Token id_attribute_;
  // A weak pointer to a NamedNodeMap that proxies the actual attributes.
  // This heavy weight object is kept in memory only when needed by the user.
  base::WeakPtr<NamedNodeMap> named_node_map_;
  // Lazily created list of CSS classes.
  // After creation this is kept in memory because of the significant negative
  // performance impact of repeatedly recreating it.
  scoped_refptr<DOMTokenList> class_list_;

  // A set of all animations currently applied to this element.
  scoped_refptr<web_animations::AnimationSet> animations_;
};

}  // namespace dom
}  // namespace cobalt

#endif  // COBALT_DOM_ELEMENT_H_
