/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef InspectorDOMAgent_h
#define InspectorDOMAgent_h

#include "core/CoreExport.h"
#include "core/events/EventListenerMap.h"
#include "core/inspector/InspectorBaseAgent.h"
#include "core/inspector/InspectorHighlight.h"
#include "core/inspector/protocol/DOM.h"
#include "core/style/ComputedStyleConstants.h"
#include "platform/geometry/FloatQuad.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
#include "wtf/text/AtomicString.h"
#include <memory>
#include <v8-inspector.h>

namespace blink {

class CharacterData;
class DOMEditor;
class Document;
class DocumentLoader;
class Element;
class EventTarget;
class ExceptionState;
class FloatQuad;
class HTMLSlotElement;
class InsertionPoint;
class InspectedFrames;
class InspectorHistory;
class Node;
class QualifiedName;
class PseudoElement;
class PlatformGestureEvent;
class PlatformMouseEvent;
class PlatformTouchEvent;
class InspectorRevalidateDOMTask;
class ShadowRoot;

class CORE_EXPORT InspectorDOMAgent final
    : public InspectorBaseAgent<protocol::DOM::Metainfo> {
  WTF_MAKE_NONCOPYABLE(InspectorDOMAgent);

 public:
  struct CORE_EXPORT DOMListener : public GarbageCollectedMixin {
    virtual ~DOMListener() {}
    virtual void didRemoveDocument(Document*) = 0;
    virtual void didRemoveDOMNode(Node*) = 0;
    virtual void didModifyDOMAttr(Element*) = 0;
  };

  enum SearchMode {
    NotSearching,
    SearchingForNormal,
    SearchingForUAShadow,
    ShowLayoutEditor
  };

  class Client {
   public:
    virtual ~Client() {}
    virtual void hideHighlight() {}
    virtual void highlightNode(Node*,
                               const InspectorHighlightConfig&,
                               bool omitTooltip) {}
    virtual void highlightQuad(std::unique_ptr<FloatQuad>,
                               const InspectorHighlightConfig&) {}
    virtual void setInspectMode(SearchMode searchMode,
                                std::unique_ptr<InspectorHighlightConfig>) {}
    virtual void setInspectedNode(Node*) {}
  };

  static String toErrorString(ExceptionState&);
  static bool getPseudoElementType(PseudoId, String*);
  static ShadowRoot* userAgentShadowRoot(Node*);

  InspectorDOMAgent(v8::Isolate*,
                    InspectedFrames*,
                    v8_inspector::V8InspectorSession*,
                    Client*);
  ~InspectorDOMAgent() override;
  DECLARE_VIRTUAL_TRACE();

  void restore() override;

  HeapVector<Member<Document>> documents();
  void reset();

  // Methods called from the frontend for DOM nodes inspection.
  void enable(ErrorString*) override;
  void disable(ErrorString*) override;
  void getDocument(ErrorString*,
                   const Maybe<int>& depth,
                   const Maybe<bool>& traverseFrames,
                   std::unique_ptr<protocol::DOM::Node>* root) override;
  void collectClassNamesFromSubtree(
      ErrorString*,
      int nodeId,
      std::unique_ptr<protocol::Array<String>>* classNames) override;
  void requestChildNodes(ErrorString*,
                         int nodeId,
                         const Maybe<int>& depth,
                         const Maybe<bool>& traverseFrames) override;
  void querySelector(ErrorString*,
                     int nodeId,
                     const String& selector,
                     int* outNodeId) override;
  void querySelectorAll(
      ErrorString*,
      int nodeId,
      const String& selector,
      std::unique_ptr<protocol::Array<int>>* nodeIds) override;
  void setNodeName(ErrorString*,
                   int nodeId,
                   const String& name,
                   int* outNodeId) override;
  void setNodeValue(ErrorString*, int nodeId, const String& value) override;
  void removeNode(ErrorString*, int nodeId) override;
  void setAttributeValue(ErrorString*,
                         int nodeId,
                         const String& name,
                         const String& value) override;
  void setAttributesAsText(ErrorString*,
                           int nodeId,
                           const String& text,
                           const Maybe<String>& name) override;
  void removeAttribute(ErrorString*, int nodeId, const String& name) override;
  void getOuterHTML(ErrorString*, int nodeId, String* outerHTML) override;
  void setOuterHTML(ErrorString*, int nodeId, const String& outerHTML) override;
  void performSearch(ErrorString*,
                     const String& query,
                     const Maybe<bool>& includeUserAgentShadowDOM,
                     String* searchId,
                     int* resultCount) override;
  void getSearchResults(
      ErrorString*,
      const String& searchId,
      int fromIndex,
      int toIndex,
      std::unique_ptr<protocol::Array<int>>* nodeIds) override;
  void discardSearchResults(ErrorString*, const String& searchId) override;
  void requestNode(ErrorString*,
                   const String& objectId,
                   int* outNodeId) override;
  void setInspectMode(ErrorString*,
                      const String& mode,
                      const Maybe<protocol::DOM::HighlightConfig>&) override;
  void highlightRect(ErrorString*,
                     int x,
                     int y,
                     int width,
                     int height,
                     const Maybe<protocol::DOM::RGBA>& color,
                     const Maybe<protocol::DOM::RGBA>& outlineColor) override;
  void highlightQuad(ErrorString*,
                     std::unique_ptr<protocol::Array<double>> quad,
                     const Maybe<protocol::DOM::RGBA>& color,
                     const Maybe<protocol::DOM::RGBA>& outlineColor) override;
  void highlightNode(ErrorString*,
                     std::unique_ptr<protocol::DOM::HighlightConfig>,
                     const Maybe<int>& nodeId,
                     const Maybe<int>& backendNodeId,
                     const Maybe<String>& objectId) override;
  void hideHighlight(ErrorString*) override;
  void highlightFrame(
      ErrorString*,
      const String& frameId,
      const Maybe<protocol::DOM::RGBA>& contentColor,
      const Maybe<protocol::DOM::RGBA>& contentOutlineColor) override;
  void pushNodeByPathToFrontend(ErrorString*,
                                const String& path,
                                int* outNodeId) override;
  void pushNodesByBackendIdsToFrontend(
      ErrorString*,
      std::unique_ptr<protocol::Array<int>> backendNodeIds,
      std::unique_ptr<protocol::Array<int>>* nodeIds) override;
  void setInspectedNode(ErrorString*, int nodeId) override;
  void resolveNode(
      ErrorString*,
      int nodeId,
      const Maybe<String>& objectGroup,
      std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>*)
      override;
  void getAttributes(
      ErrorString*,
      int nodeId,
      std::unique_ptr<protocol::Array<String>>* attributes) override;
  void copyTo(ErrorString*,
              int nodeId,
              int targetNodeId,
              const Maybe<int>& insertBeforeNodeId,
              int* outNodeId) override;
  void moveTo(ErrorString*,
              int nodeId,
              int targetNodeId,
              const Maybe<int>& insertBeforeNodeId,
              int* outNodeId) override;
  void undo(ErrorString*) override;
  void redo(ErrorString*) override;
  void markUndoableState(ErrorString*) override;
  void focus(ErrorString*, int nodeId) override;
  void setFileInputFiles(
      ErrorString*,
      int nodeId,
      std::unique_ptr<protocol::Array<String>> files) override;
  void getBoxModel(ErrorString*,
                   int nodeId,
                   std::unique_ptr<protocol::DOM::BoxModel>*) override;
  void getNodeForLocation(ErrorString*, int x, int y, int* outNodeId) override;
  void getRelayoutBoundary(ErrorString*, int nodeId, int* outNodeId) override;
  void getHighlightObjectForTest(
      ErrorString*,
      int nodeId,
      std::unique_ptr<protocol::DictionaryValue>* highlight) override;

  bool enabled() const;
  void releaseDanglingNodes();

  // Methods called from the InspectorInstrumentation.
  void domContentLoadedEventFired(LocalFrame*);
  void didCommitLoad(LocalFrame*, DocumentLoader*);
  void didInsertDOMNode(Node*);
  void willRemoveDOMNode(Node*);
  void willModifyDOMAttr(Element*,
                         const AtomicString& oldValue,
                         const AtomicString& newValue);
  void didModifyDOMAttr(Element*,
                        const QualifiedName&,
                        const AtomicString& value);
  void didRemoveDOMAttr(Element*, const QualifiedName&);
  void styleAttributeInvalidated(const HeapVector<Member<Element>>& elements);
  void characterDataModified(CharacterData*);
  void didInvalidateStyleAttr(Node*);
  void didPushShadowRoot(Element* host, ShadowRoot*);
  void willPopShadowRoot(Element* host, ShadowRoot*);
  void didPerformElementShadowDistribution(Element*);
  void didPerformSlotDistribution(HTMLSlotElement*);
  void frameDocumentUpdated(LocalFrame*);
  void pseudoElementCreated(PseudoElement*);
  void pseudoElementDestroyed(PseudoElement*);

  Node* nodeForId(int nodeId);
  int boundNodeId(Node*);
  void setDOMListener(DOMListener*);
  void inspect(Node*);
  void nodeHighlightedInOverlay(Node*);
  int pushNodePathToFrontend(Node*);

  static String documentURLString(Document*);

  std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>
  resolveNode(Node*, const String& objectGroup);

  InspectorHistory* history() { return m_history.get(); }

  // We represent embedded doms as a part of the same hierarchy. Hence we treat
  // children of frame owners differently.  We also skip whitespace text nodes
  // conditionally. Following methods encapsulate these specifics.
  static Node* innerFirstChild(Node*);
  static Node* innerNextSibling(Node*);
  static Node* innerPreviousSibling(Node*);
  static unsigned innerChildNodeCount(Node*);
  static Node* innerParentNode(Node*);
  static bool isWhitespace(Node*);

  Node* assertNode(ErrorString*, int nodeId);
  Element* assertElement(ErrorString*, int nodeId);
  Document* assertDocument(ErrorString*, int nodeId);
  Document* document() const { return m_document.get(); }

 private:
  void setDocument(Document*);
  void innerEnable();

  void setSearchingForNode(ErrorString*,
                           SearchMode,
                           const Maybe<protocol::DOM::HighlightConfig>&);
  std::unique_ptr<InspectorHighlightConfig> highlightConfigFromInspectorObject(
      ErrorString*,
      const Maybe<protocol::DOM::HighlightConfig>& highlightInspectorObject);

  // Node-related methods.
  typedef HeapHashMap<Member<Node>, int> NodeToIdMap;
  int bind(Node*, NodeToIdMap*);
  void unbind(Node*, NodeToIdMap*);

  Node* assertEditableNode(ErrorString*, int nodeId);
  Node* assertEditableChildNode(ErrorString*,
                                Element* parentElement,
                                int nodeId);
  Element* assertEditableElement(ErrorString*, int nodeId);

  int pushNodePathToFrontend(Node*, NodeToIdMap* nodeMap);
  void pushChildNodesToFrontend(int nodeId,
                                int depth = 1,
                                bool traverseFrames = false);

  void invalidateFrameOwnerElement(LocalFrame*);

  std::unique_ptr<protocol::DOM::Node> buildObjectForNode(Node*,
                                                          int depth,
                                                          bool traverseFrames,
                                                          NodeToIdMap*);
  std::unique_ptr<protocol::Array<String>> buildArrayForElementAttributes(
      Element*);
  std::unique_ptr<protocol::Array<protocol::DOM::Node>>
  buildArrayForContainerChildren(Node* container,
                                 int depth,
                                 bool traverseFrames,
                                 NodeToIdMap* nodesMap);
  std::unique_ptr<protocol::Array<protocol::DOM::Node>>
  buildArrayForPseudoElements(Element*, NodeToIdMap* nodesMap);
  std::unique_ptr<protocol::Array<protocol::DOM::BackendNode>>
  buildArrayForDistributedNodes(InsertionPoint*);
  std::unique_ptr<protocol::Array<protocol::DOM::BackendNode>>
  buildDistributedNodesForSlot(HTMLSlotElement*);

  Node* nodeForPath(const String& path);
  Node* nodeForRemoteId(ErrorString*, const String& id);

  void discardFrontendBindings();

  void innerHighlightQuad(std::unique_ptr<FloatQuad>,
                          const Maybe<protocol::DOM::RGBA>& color,
                          const Maybe<protocol::DOM::RGBA>& outlineColor);

  bool pushDocumentUponHandlelessOperation(ErrorString*);

  Member<InspectorRevalidateDOMTask> revalidateTask();

  v8::Isolate* m_isolate;
  Member<InspectedFrames> m_inspectedFrames;
  v8_inspector::V8InspectorSession* m_v8Session;
  Client* m_client;
  Member<DOMListener> m_domListener;
  Member<NodeToIdMap> m_documentNodeToIdMap;
  // Owns node mappings for dangling nodes.
  HeapVector<Member<NodeToIdMap>> m_danglingNodeToIdMaps;
  HeapHashMap<int, Member<Node>> m_idToNode;
  HeapHashMap<int, Member<NodeToIdMap>> m_idToNodesMap;
  HashSet<int> m_childrenRequested;
  HashSet<int> m_distributedNodesRequested;
  HashMap<int, int> m_cachedChildCount;
  int m_lastNodeId;
  Member<Document> m_document;
  typedef HeapHashMap<String, HeapVector<Member<Node>>> SearchResults;
  SearchResults m_searchResults;
  Member<InspectorRevalidateDOMTask> m_revalidateTask;
  Member<InspectorHistory> m_history;
  Member<DOMEditor> m_domEditor;
  bool m_suppressAttributeModifiedEvent;
  int m_backendNodeIdToInspect;
};

}  // namespace blink

#endif  // !defined(InspectorDOMAgent_h)
