/*
 * Copyright (C) 2007, 2008, 2013, 2015 Apple Inc.  All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * 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 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.
 */

WI.DOMTreeOutline = class DOMTreeOutline extends WI.TreeOutline
{
    constructor({selectable, omitRootDOMNode, excludeRevealElementContextMenu, showInspectedNode} = {})
    {
        super(selectable);

        this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
        this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
        this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
        this.element.addEventListener("dragstart", this._ondragstart.bind(this), false);
        this.element.addEventListener("dragover", this._ondragover.bind(this), false);
        this.element.addEventListener("dragleave", this._ondragleave.bind(this), false);
        this.element.addEventListener("drop", this._ondrop.bind(this), false);
        this.element.addEventListener("dragend", this._ondragend.bind(this), false);

        this.element.classList.add("dom", WI.SyntaxHighlightedStyleClassName);
        this.element.dir = "ltr";
        this.element.role = "tree";

        this._includeRootDOMNode = !omitRootDOMNode;
        this._excludeRevealElementContextMenu = excludeRevealElementContextMenu;
        this._rootDOMNode = null;
        this._selectedDOMNode = null;
        this._treeElementsToRemove = null;

        this._editable = false;
        this._editing = false;
        this._visible = false;
        this._usingLocalDOMNode = false;

        this._hideElementsKeyboardShortcut = new WI.KeyboardShortcut(null, "H", this._hideElements.bind(this), this.element);
        this._hideElementsKeyboardShortcut.implicitlyPreventsDefault = false;

        if (showInspectedNode)
            WI.domManager.addEventListener(WI.DOMManager.Event.InspectedNodeChanged, this._handleInspectedNodeChanged, this);
    }

    // Public

    wireToDomAgent()
    {
        this._elementsTreeUpdater = new WI.DOMTreeUpdater(this);
    }

    close()
    {
        if (this._elementsTreeUpdater) {
            this._elementsTreeUpdater.close();
            this._elementsTreeUpdater = null;
        }
    }

    setVisible(visible, omitFocus)
    {
        this._visible = visible;
        if (!this._visible)
            return;

        this._updateModifiedNodes();

        if (this._selectedDOMNode)
            this._revealAndSelectNode(this._selectedDOMNode, omitFocus);

        this.update();
    }

    get rootDOMNode()
    {
        return this._rootDOMNode;
    }

    set rootDOMNode(x)
    {
        if (this._rootDOMNode === x)
            return;

        this._rootDOMNode = x;

        this._isXMLMimeType = x && x.isXMLNode();

        this.update();
    }

    get isXMLMimeType()
    {
        return this._isXMLMimeType;
    }

    markAsUsingLocalDOMNode()
    {
        this._editable = false;
        this._usingLocalDOMNode = true;
    }

    selectedDOMNode()
    {
        return this._selectedDOMNode;
    }

    selectDOMNode(node, focus)
    {
        if (this._selectedDOMNode === node) {
            this._revealAndSelectNode(node, !focus);
            return;
        }

        this._selectedDOMNode = node;
        this._revealAndSelectNode(node, !focus);

        // The _revealAndSelectNode() method might find a different element if there is inlined text,
        // and the select() call would change the selectedDOMNode and reenter this setter. So to
        // avoid calling _selectedNodeChanged() twice, first check if _selectedDOMNode is the same
        // node as the one passed in.
        // Note that _revealAndSelectNode will not do anything for a null node.
        if (!node || this._selectedDOMNode === node)
            this._selectedNodeChanged();
    }

    get editable()
    {
        return this._editable && this.rootDOMNode && !this.rootDOMNode.destroyed;
    }

    set editable(x)
    {
        this._editable = x;
    }

    get editing()
    {
        return this._editing;
    }

    update()
    {
        if (!this.rootDOMNode)
            return;

        let selectedTreeElements = this.selectedTreeElements;

        this.removeChildren();

        var treeElement;
        if (this._includeRootDOMNode) {
            treeElement = new WI.DOMTreeElement(this.rootDOMNode);
            treeElement.selectable = this.selectable;
            this.appendChild(treeElement);
        } else {
            // FIXME: this could use findTreeElement to reuse a tree element if it already exists
            var node = this.rootDOMNode.firstChild;
            while (node) {
                treeElement = new WI.DOMTreeElement(node);
                treeElement.selectable = this.selectable;
                this.appendChild(treeElement);
                node = node.nextSibling;

                if (treeElement.hasChildren && !treeElement.expanded)
                    treeElement.expand();
            }
        }

        if (!selectedTreeElements.length)
            return;

        // The selection cannot be restored from represented objects alone,
        // since a closing tag DOMTreeElement has the same represented object
        // as its parent.
        selectedTreeElements = selectedTreeElements.map((oldTreeElement) => {
            let treeElement = this.findTreeElement(oldTreeElement.representedObject);
            if (treeElement && oldTreeElement.isCloseTag()) {
                console.assert(treeElement.closeTagTreeElement, "Missing close tag TreeElement.", treeElement);
                if (treeElement.closeTagTreeElement)
                    treeElement = treeElement.closeTagTreeElement;
            }
            return treeElement;
        });

        // It's possible that a previously selected node will no longer exist (e.g. after navigation).
        selectedTreeElements = selectedTreeElements.filter((x) => !!x);

        if (!selectedTreeElements.length)
            return;

        this.selectTreeElements(selectedTreeElements);

        if (this.selectedTreeElement)
            this.selectedTreeElement.reveal();
    }

    updateSelectionArea()
    {
        // This will miss updating selection areas used for the hovered tree element and
        // and those used to show forced pseudo class indicators, but this should be okay.
        // The hovered element will update when user moves the mouse, and indicators don't need the
        // selection area height to be accurate since they use ::before to place the indicator.
        let selectedTreeElements = this.selectedTreeElements;
        for (let treeElement of selectedTreeElements)
            treeElement.updateSelectionArea();
    }

    toggleSelectedElementsVisibility(forceHidden)
    {
        for (let treeElement of this.selectedTreeElements)
            treeElement.toggleElementVisibility(forceHidden);
    }

    _selectedNodeChanged()
    {
        this.dispatchEventToListeners(WI.DOMTreeOutline.Event.SelectedNodeChanged);
    }

    findTreeElement(node)
    {
        let isAncestorNode = (ancestor, node) => ancestor.isAncestor(node);
        let parentNode = (node) => node.parentNode;
        let treeElement = super.findTreeElement(node, isAncestorNode, parentNode);
        if (!treeElement && node.nodeType() === Node.TEXT_NODE) {
            // The text node might have been inlined if it was short, so try to find the parent element.
            treeElement = super.findTreeElement(node.parentNode, isAncestorNode, parentNode);
        }

        return treeElement;
    }

    createTreeElementFor(node)
    {
        var treeElement = this.findTreeElement(node);
        if (treeElement)
            return treeElement;

        if (!node.parentNode)
            return null;

        treeElement = this.createTreeElementFor(node.parentNode);
        if (!treeElement)
            return null;

        return treeElement.showChildNode(node);
    }

    set suppressRevealAndSelect(x)
    {
        if (this._suppressRevealAndSelect === x)
            return;
        this._suppressRevealAndSelect = x;
    }

    populateContextMenu(contextMenu, event, treeElement)
    {
        let subMenus = {
            add: new WI.ContextSubMenuItem(contextMenu, WI.UIString("Add")),
            edit: new WI.ContextSubMenuItem(contextMenu, WI.UIString("Edit")),
            copy: new WI.ContextSubMenuItem(contextMenu, WI.UIString("Copy")),
            delete: new WI.ContextSubMenuItem(contextMenu, WI.UIString("Delete")),
        };

        if (this.editable && treeElement.selected && this.selectedTreeElements.length > 1) {
            subMenus.delete.appendItem(WI.UIString("Nodes"), () => {
                this.ondelete();
            });
        }

        if (treeElement.populateDOMNodeContextMenu)
            treeElement.populateDOMNodeContextMenu(contextMenu, subMenus, event, subMenus);

        let options = {
            disallowEditing: !this.editable,
            usingLocalDOMNode: this._usingLocalDOMNode,
            excludeRevealElement: this._excludeRevealElementContextMenu,
            copySubMenu: subMenus.copy,
        };

        if (treeElement.bindRevealDescendantBreakpointsMenuItemHandler)
            options.revealDescendantBreakpointsMenuItemHandler = treeElement.bindRevealDescendantBreakpointsMenuItemHandler();

        WI.appendContextMenuItemsForDOMNode(contextMenu, treeElement.representedObject, options);

        super.populateContextMenu(contextMenu, event, treeElement);
    }

    adjustCollapsedRange()
    {
    }

    ondelete()
    {
        if (!this.editable)
            return false;

        this._treeElementsToRemove = this.selectedTreeElements;

        // Reveal all of the elements being deleted so that if the node is hidden (e.g. the parent
        // is collapsed), we can select its siblings instead of the parent itself.
        for (let treeElement of this._treeElementsToRemove)
            treeElement.reveal();

        this._selectionController.removeSelectedItems();

        let levelMap = new Map;

        function getLevel(treeElement) {
            let level = levelMap.get(treeElement);
            if (isNaN(level)) {
                level = 0;
                let current = treeElement;
                while (current = current.parent)
                    level++;
                levelMap.set(treeElement, level);
            }
            return level;
        }

        // Sort in descending order by node level. This ensures that child nodes
        // are removed before their ancestors.
        this._treeElementsToRemove.sort((a, b) => getLevel(b) - getLevel(a));

        // Track removed elements, since the opening and closing tags for the
        // same WI.DOMNode can both be selected.
        let removedDOMNodes = new Set;

        for (let treeElement of this._treeElementsToRemove) {
            if (removedDOMNodes.has(treeElement.representedObject))
                continue;
            removedDOMNodes.add(treeElement.representedObject);
            treeElement.remove();
        }

        this._treeElementsToRemove = null;

        if (this.selectedTreeElement && !this.selectedTreeElement.isCloseTag()) {
            console.assert(this.selectedTreeElements.length === 1);
            this.selectedTreeElement.reveal();
        }

        return true;
    }

    // SelectionController delegate overrides

    selectionControllerPreviousSelectableItem(controller, item)
    {
        let treeElement = this.getCachedTreeElement(item);
        console.assert(treeElement, "Missing TreeElement for representedObject.", item);
        if (!treeElement)
            return null;

        if (this._treeElementsToRemove) {
            // When deleting, force the SelectionController to check siblings in
            // the opposite direction before searching up the parent chain.
            if (!treeElement.previousSelectableSibling && treeElement.nextSelectableSibling)
                return null;
        }

        return super.selectionControllerPreviousSelectableItem(controller, item);
    }

    // Protected

    canSelectTreeElement(treeElement)
    {
        if (!super.canSelectTreeElement(treeElement))
            return false;

        let willRemoveAncestorOrSelf = false;
        if (this._treeElementsToRemove) {
            while (treeElement && !willRemoveAncestorOrSelf) {
                willRemoveAncestorOrSelf = this._treeElementsToRemove.includes(treeElement);
                treeElement = treeElement.parent;
            }
        }

        return !willRemoveAncestorOrSelf;
    }

    objectForSelection(treeElement)
    {
        if (treeElement instanceof WI.DOMTreeElement && treeElement.isCloseTag()) {
            // SelectionController requires every selectable item to be unique.
            // The DOMTreeElement for a close tag has the same represented object
            // as it's parent (the open tag). Return a proxy object associated
            // with the tree element for the close tag so it can be selected.
            if (!treeElement.__closeTagProxyObject)
                treeElement.__closeTagProxyObject = {__proxyObjectTreeElement: treeElement};
            return treeElement.__closeTagProxyObject;
        }

        return super.objectForSelection(treeElement);
    }

    // Private

    _revealAndSelectNode(node, omitFocus)
    {
        if (!node || this._suppressRevealAndSelect)
            return;

        var treeElement = this.createTreeElementFor(node);
        if (!treeElement)
            return;

        treeElement.revealAndSelect(omitFocus);
    }

    _onmousedown(event)
    {
        let element = this.treeElementFromEvent(event);
        if (!element || element.isEventWithinDisclosureTriangle(event)) {
            event.preventDefault();
            return;
        }
    }

    _onmousemove(event)
    {
        if (this._usingLocalDOMNode)
            return;

        let element = this.treeElementFromEvent(event);
        if (element && this._previousHoveredElement === element)
            return;

        if (this._previousHoveredElement) {
            this._previousHoveredElement.hovered = false;
            this._previousHoveredElement = null;
        }

        if (element) {
            element.hovered = true;
            this._previousHoveredElement = element;

            if (element.representedObject) {
                // Lazily compute tag-specific tooltips.
                if (!element.tooltip && element._createTooltipForNode)
                    element._createTooltipForNode();

                element.representedObject.highlight();
            } else
                WI.domManager.hideDOMNodeHighlight();
        } else
            WI.domManager.hideDOMNodeHighlight();
    }

    _onmouseout(event)
    {
        if (this._usingLocalDOMNode)
            return;

        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
        if (nodeUnderMouse && this.element.contains(nodeUnderMouse))
            return;

        if (this._previousHoveredElement) {
            this._previousHoveredElement.hovered = false;
            this._previousHoveredElement = null;
        }

        WI.domManager.hideDOMNodeHighlight();
    }

    _ondragstart(event)
    {
        if (!this.editable)
            return false;

        let treeElement = this.treeElementFromEvent(event);
        if (!treeElement)
            return false;

        event.dataTransfer.effectAllowed = "copyMove";
        event.dataTransfer.setData(DOMTreeOutline.DOMNodeIdDragType, treeElement.representedObject.id);

        if (!this._isValidDragSourceOrTarget(treeElement))
            return false;

        if (treeElement.representedObject.nodeName() === "BODY" || treeElement.representedObject.nodeName() === "HEAD")
            return false;

        event.dataTransfer.setData("text/plain", treeElement.listItemElement.textContent);
        this._nodeBeingDragged = treeElement.representedObject;

        WI.domManager.hideDOMNodeHighlight();

        return true;
    }

    _ondragover(event)
    {
        if (!this.editable)
            return false;

        if (event.dataTransfer.types.includes(WI.GeneralStyleDetailsSidebarPanel.ToggledClassesDragType)) {
            event.preventDefault();
            event.dataTransfer.dropEffect = "copy";
            return false;
        }

        if (!this._nodeBeingDragged)
            return false;

        let treeElement = this.treeElementFromEvent(event);
        if (!this._isValidDragSourceOrTarget(treeElement))
            return false;

        let node = treeElement.representedObject;
        while (node) {
            if (node === this._nodeBeingDragged)
                return false;
            node = node.parentNode;
        }

        this.dragOverTreeElement = treeElement;
        treeElement.listItemElement.classList.add("elements-drag-over");
        treeElement.updateSelectionArea();

        event.preventDefault();
        event.dataTransfer.dropEffect = "move";
        return false;
    }

    _ondragleave(event)
    {
        if (!this.editable)
            return false;

        this._clearDragOverTreeElementMarker();
        event.preventDefault();
        return false;
    }

    _isValidDragSourceOrTarget(treeElement)
    {
        if (!treeElement)
            return false;

        var node = treeElement.representedObject;
        if (!(node instanceof WI.DOMNode))
            return false;

        if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE)
            return false;

        return true;
    }

    _ondrop(event)
    {
        if (!this.editable)
            return;

        event.preventDefault();

        function callback(error, newNodeId)
        {
            if (error)
                return;

            this._updateModifiedNodes();
            var newNode = WI.domManager.nodeForId(newNodeId);
            if (newNode)
                this.selectDOMNode(newNode, true);
        }

        let treeElement = this.treeElementFromEvent(event);
        if (this._nodeBeingDragged && treeElement) {
            let parentNode = null;
            let anchorNode = null;

            if (treeElement._elementCloseTag) {
                // Drop onto closing tag -> insert as last child.
                parentNode = treeElement.representedObject;
            } else {
                let dragTargetNode = treeElement.representedObject;
                parentNode = dragTargetNode.parentNode;
                anchorNode = dragTargetNode;
            }

            this._nodeBeingDragged.moveTo(parentNode, anchorNode, callback.bind(this));
        } else {
            let className = event.dataTransfer.getData(WI.GeneralStyleDetailsSidebarPanel.ToggledClassesDragType);
            if (className && treeElement)
                treeElement.representedObject.toggleClass(className, true);
        }

        delete this._nodeBeingDragged;
    }

    _ondragend(event)
    {
        if (!this.editable)
            return;

        event.preventDefault();
        this._clearDragOverTreeElementMarker();
        delete this._nodeBeingDragged;
    }

    _clearDragOverTreeElementMarker()
    {
        if (this.dragOverTreeElement) {
            let element = this.dragOverTreeElement;
            this.dragOverTreeElement = null;

            element.listItemElement.classList.remove("elements-drag-over");
            element.updateSelectionArea();
        }
    }

    _updateModifiedNodes()
    {
        if (this._elementsTreeUpdater)
            this._elementsTreeUpdater._updateModifiedNodes();
    }

    _handleInspectedNodeChanged(event)
    {
        let {lastInspectedNode} = event.data;

        if (lastInspectedNode) {
            let lastInspectedNodeTreeElement = this.findTreeElement(lastInspectedNode);
            if (lastInspectedNodeTreeElement)
                lastInspectedNodeTreeElement.listItemElement.classList.remove("inspected-node");
        }

        let inspectedNodeTreeElement = this.findTreeElement(WI.domManager.inspectedNode);
        if (inspectedNodeTreeElement)
            inspectedNodeTreeElement.listItemElement.classList.add("inspected-node");
    }

    _hideElements(event, keyboardShortcut)
    {
        if (!this.editable)
            return;

        if (!this.selectedTreeElement || WI.isEditingAnyField())
            return;

        event.preventDefault();

        let forceHidden = !this.selectedTreeElements.every((treeElement) => treeElement.isNodeHidden);
        this.toggleSelectedElementsVisibility(forceHidden);
    }
};

WI.DOMTreeOutline.Event = {
    SelectedNodeChanged: "dom-tree-outline-selected-node-changed"
};

WI.DOMTreeOutline.DOMNodeIdDragType = "web-inspector/dom-node-id";
