// 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_NODE_H_
#define COBALT_DOM_NODE_H_

#include <string>
#include <vector>

#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "cobalt/base/token.h"
#include "cobalt/dom/event_target.h"
#include "cobalt/dom/mutation_observer.h"
#include "cobalt/dom/mutation_observer_init.h"
#include "cobalt/dom/registered_observer_list.h"

namespace cobalt {
namespace dom {

class CDATASection;
class Comment;
class Document;
class DocumentType;
class Element;
class HTMLCollection;
class NodeList;
class Text;

// Used to implement type-safe visiting via double-dispatch on a class
// hierarchy of Node objects.
class NodeVisitor {
 public:
  virtual void Visit(CDATASection* cdata_section) = 0;
  virtual void Visit(Comment* comment) = 0;
  virtual void Visit(Document* document) = 0;
  virtual void Visit(DocumentType* document_type) = 0;
  virtual void Visit(Element* element) = 0;
  virtual void Visit(Text* text) = 0;

 protected:
  ~NodeVisitor() {}
};

class ConstNodeVisitor {
 public:
  virtual void Visit(const CDATASection* cdata_section) = 0;
  virtual void Visit(const Comment* comment) = 0;
  virtual void Visit(const Document* document) = 0;
  virtual void Visit(const DocumentType* document_type) = 0;
  virtual void Visit(const Element* element) = 0;
  virtual void Visit(const Text* text) = 0;

 protected:
  ~ConstNodeVisitor() {}
};

// A Node is an interface from which a number of DOM types inherit, and allows
// these various types to be treated (or tested) similarly.
//   https://www.w3.org/TR/dom/#interface-node
//
// Memory management:
// ------------------
// All Node types are reference counted and support weak pointers.
// While this should be enough to prevent memory leaks in most situations,
// there are certain conditions where a memory leak can occur. A notable
// example is a circular reference between DOM and JavaScript:
//   http://www.javascriptkit.com/javatutors/closuresleak/index3.shtml
//
// Using strong shared references, each node owns its first child and next
// sibling. The references to parent and previous sibling are weak. In addition,
// a JavaScript wrapper, which is a JavaScript reference for a node, will also
// have a strong shared reference to the node, and the bindings layer ensures
// that a JavaScript wrapper exists for all ancestors of the node.
// As a result, any JavaScript reference to a node will keep the whole DOM tree
// that the node belongs to alive, which is a conforming behavior.
//
class Node : public EventTarget {
 public:
  // Web API: Node
  // NodeType values as defined by Web API Node.nodeType.
  typedef uint16 NodeType;  // Work around lack of strongly-typed enums
                            // in C++03.
  enum NodeTypeInternal {   // A name is given only to pacify the compiler.
                            // Use |NodeType| instead.
    kElementNode = 1,
    kTextNode = 3,
    kCdataSectionNode = 4,
    kCommentNode = 8,
    kDocumentNode = 9,
    kDocumentTypeNode = 10,
  };

  // Custom, not in any spec.
  // Node generation constants.
  enum NodeGeneration {
    kInvalidNodeGeneration = 0,
    kInitialNodeGeneration = 1,
  };

  // Web API: EventTarget
  //
  bool DispatchEvent(const scoped_refptr<Event>& event) OVERRIDE;

  // Web API: Node
  //
  virtual NodeType node_type() const = 0;
  virtual base::Token node_name() const = 0;

  scoped_refptr<Document> owner_document() const;
  scoped_refptr<Node> parent_node() const { return parent_; }
  scoped_refptr<Element> parent_element() const;
  bool HasChildNodes() const;
  scoped_refptr<NodeList> child_nodes() const;
  scoped_refptr<Node> first_child() const { return first_child_; }
  scoped_refptr<Node> last_child() const { return last_child_; }
  scoped_refptr<Node> next_sibling() const { return next_sibling_; }
  scoped_refptr<Node> previous_sibling() const { return previous_sibling_; }

  virtual base::optional<std::string> node_value() const {
    return base::nullopt;
  }
  virtual void set_node_value(
      const base::optional<std::string>& /* node_value */) {}

  virtual base::optional<std::string> text_content() const {
    return base::nullopt;
  }
  virtual void set_text_content(
      const base::optional<std::string>& /* text_content */) {}

  scoped_refptr<Node> CloneNode(bool deep) const;

  bool Contains(const scoped_refptr<Node>& other_name) const;

  scoped_refptr<Node> InsertBefore(const scoped_refptr<Node>& new_child,
                                   const scoped_refptr<Node>& reference_child);
  scoped_refptr<Node> AppendChild(const scoped_refptr<Node>& new_child);
  scoped_refptr<Node> ReplaceChild(const scoped_refptr<Node>& node,
                                   const scoped_refptr<Node>& child);
  scoped_refptr<Node> RemoveChild(const scoped_refptr<Node>& node);

  // Web API: ParentNode (implements)
  // The ParentNode interface contains methods that are particular to Node
  // objects that can have children.
  //   https://www.w3.org/TR/dom/#parentnode
  //
  scoped_refptr<HTMLCollection> children() const;
  scoped_refptr<Element> first_element_child() const;
  scoped_refptr<Element> last_element_child() const;
  unsigned int child_element_count() const;

  scoped_refptr<Element> QuerySelector(const std::string& selectors);
  scoped_refptr<NodeList> QuerySelectorAll(const std::string& selectors);

  // Web API: NonDocumentTypeChildNode (implements)
  // The NonDocumentTypeChildNode interface contains methods that are particular
  // to Node objects that can have a parent.
  //   https://www.w3.org/TR/2014/WD-dom-20140710/#interface-nondocumenttypechildnode
  scoped_refptr<Element> previous_element_sibling() const;
  scoped_refptr<Element> next_element_sibling() const;

  // From the spec: Node.
  //
  // A node's node document can be changed by the adopt algorithm.
  //   https://www.w3.org/TR/dom/#concept-node-adopt
  void AdoptIntoDocument(Document* document);

  // Each node has an associated node document, set upon creation, that is a
  // document.
  //   https://www.w3.org/TR/dom/#concept-node-document
  // Returns the node document if it still exists, NULL if not.
  Document* node_document() const { return node_document_.get(); }

  // Custom, not in any spec.
  //
  virtual bool HasAttributes() const { return false; }

  // Returns the root Node of the tree this node belongs to. If this node is the
  // root, it will return this Node.
  scoped_refptr<Node> GetRootNode();

  bool IsCDATASection() const { return node_type() == kCdataSectionNode; }
  bool IsComment() const { return node_type() == kCommentNode; }
  bool IsDocument() const { return node_type() == kDocumentNode; }
  bool IsDocumentType() const { return node_type() == kDocumentTypeNode; }
  bool IsElement() const { return node_type() == kElementNode; }
  bool IsText() const { return node_type() == kTextNode; }

  // Safe type conversion methods that will downcast to the required type if
  // possible or return NULL otherwise.
  virtual scoped_refptr<CDATASection> AsCDATASection();
  virtual scoped_refptr<Comment> AsComment();
  virtual scoped_refptr<Document> AsDocument();
  virtual scoped_refptr<DocumentType> AsDocumentType();
  virtual scoped_refptr<Element> AsElement();
  virtual scoped_refptr<Text> AsText();

  // Node generation counter that will be modified for every content change
  // that affects the topology of the subtree defined by this node.
  // The returned node generation will be never equal to kInvalidNodeGeneration.
  uint32_t node_generation() const { return node_generation_; }

  // Children classes implement this method to support type-safe visiting via
  // double dispatch.
  virtual void Accept(NodeVisitor* visitor) = 0;
  virtual void Accept(ConstNodeVisitor* visitor) const = 0;

  virtual scoped_refptr<Node> Duplicate() const = 0;

  // Purges all cached resource reference from the current node and all
  // descendents.
  void PurgeCachedResourceReferencesRecursively();

  bool RegisterMutationObserver(const scoped_refptr<MutationObserver>& observer,
                                const MutationObserverInit& options) {
    return registered_observers_.AddMutationObserver(observer, options);
  }
  void UnregisterMutationObserver(
      const scoped_refptr<MutationObserver>& observer) {
    registered_observers_.RemoveMutationObserver(observer);
  }

  void TraceMembers(script::Tracer* tracer) OVERRIDE;

  DEFINE_WRAPPABLE_TYPE(Node);

 protected:
  explicit Node(Document* document);
  virtual ~Node();

  // Called to notify that the node along with all its descendants has been
  // inserted to its owner document.
  virtual void OnInsertedIntoDocument();
  // Called to notify that the node along with all its descendants has been
  // removed from to its owner document.
  virtual void OnRemovedFromDocument();

  virtual bool IsInDocument() const { return inserted_into_document_; }

  virtual void PurgeCachedBackgroundImagesOfNodeAndDescendants();
  virtual void InvalidateComputedStylesOfNodeAndDescendants();
  virtual void InvalidateLayoutBoxesOfNodeAndAncestors();
  virtual void InvalidateLayoutBoxesOfNodeAndDescendants();

  virtual void InvalidateLayoutBoxSizes() {}
  virtual void InvalidateLayoutBoxCrossReferences() {}
  virtual void InvalidateLayoutBoxRenderTreeNodes() {}

  void PurgeCachedBackgroundImagesOfDescendants();
  void InvalidateComputedStylesOfDescendants();
  void InvalidateLayoutBoxesOfAncestors();
  void InvalidateLayoutBoxesOfDescendants();

  // Triggers a generation update in this node and all its ancestor nodes.
  void UpdateGenerationForNodeAndAncestors();

  // Gather a list of RegisteredObservers on this node and its ancestors.
  typedef std::vector<RegisteredObserver> RegisteredObserverVector;
  scoped_ptr<RegisteredObserverVector> GatherInclusiveAncestorsObservers();

  void ReplaceAll(const scoped_refptr<Node>& node);

 private:
  // From EventTarget.
  std::string GetDebugName() OVERRIDE { return node_name().c_str(); }

  // From the spec: Node.
  // Mutation algorithms.
  //   https://www.w3.org/TR/dom/#mutation-algorithms
  //
  bool EnsurePreInsertionValidity(const scoped_refptr<Node>& node,
                                  const scoped_refptr<Node>& child);

  scoped_refptr<Node> PreInsert(const scoped_refptr<Node>& node,
                                const scoped_refptr<Node>& child);
  void Insert(const scoped_refptr<Node>& node, const scoped_refptr<Node>& child,
              bool suppress_observers);

  scoped_refptr<Node> PreRemove(const scoped_refptr<Node>& child);
  void Remove(const scoped_refptr<Node>& node, bool suppress_observers);

  // Called everytime mutation happens, i.e. when a child is inserted or removed
  // from this node.
  virtual void OnMutation() {}

  // Weak reference to the node document.
  base::WeakPtr<Document> node_document_;
  // Weak references to parent, previous sibling and last child.
  Node* parent_;
  Node* previous_sibling_;
  Node* last_child_;
  // Whether the node has been inserted into its node document.
  bool inserted_into_document_;
  // Node generation counter.
  uint32_t node_generation_;

  // Strong references to first child and next sibling.
  scoped_refptr<Node> first_child_;
  scoped_refptr<Node> next_sibling_;

  RegisteredObserverList registered_observers_;

  DISALLOW_COPY_AND_ASSIGN(Node);
};

}  // namespace dom
}  // namespace cobalt

#endif  // COBALT_DOM_NODE_H_
