/*
 * Copyright (C) 2007, 2013, 2015 Apple 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 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.TreeElement = class TreeElement extends WI.Object
{
    constructor(title, representedObject, options = {})
    {
        super();

        this._title = title;
        this.representedObject = representedObject || {};

        if (this.representedObject.__treeElementIdentifier)
            this.identifier = this.representedObject.__treeElementIdentifier;
        else {
            this.identifier = WI.TreeOutline._knownTreeElementNextIdentifier++;
            this.representedObject.__treeElementIdentifier = this.identifier;
        }

        this._hidden = false;
        this._selectable = true;
        this.expanded = false;
        this.selected = false;
        this.hasChildren = options.hasChildren;
        this.children = [];
        this.treeOutline = null;
        this.parent = null;
        this.previousSibling = null;
        this.nextSibling = null;
        this._listItemNode = null;
    }

    // Methods

    appendChild() { return WI.TreeOutline.prototype.appendChild.apply(this, arguments); }
    insertChild() { return WI.TreeOutline.prototype.insertChild.apply(this, arguments); }
    removeChild() { return WI.TreeOutline.prototype.removeChild.apply(this, arguments); }
    removeChildAtIndex() { return WI.TreeOutline.prototype.removeChildAtIndex.apply(this, arguments); }
    removeChildren() { return WI.TreeOutline.prototype.removeChildren.apply(this, arguments); }
    selfOrDescendant() { return WI.TreeOutline.prototype.selfOrDescendant.apply(this, arguments); }

    get arrowToggleWidth()
    {
        return 10;
    }

    get selectable()
    {
        if (this._hidden)
            return false;
        return this._selectable;
    }

    set selectable(x)
    {
        this._selectable = x;
    }

    get listItemElement()
    {
        return this._listItemNode;
    }

    get title()
    {
        return this._title;
    }

    set title(x)
    {
        this._title = x;
        this._setListItemNodeContent();
        this.didChange();
    }

    get titleHTML()
    {
        return this._titleHTML;
    }

    set titleHTML(x)
    {
        this._titleHTML = x;
        this._setListItemNodeContent();
        this.didChange();
    }

    get tooltip()
    {
        return this._tooltip;
    }

    set tooltip(x)
    {
        this._tooltip = x;
        if (this._listItemNode)
            this._listItemNode.title = x ? x : "";
    }

    get hasChildren()
    {
        return this._hasChildren;
    }

    set hasChildren(x)
    {
        if (this._hasChildren === x)
            return;

        this._hasChildren = x;

        if (!this._listItemNode)
            return;

        if (x)
            this._listItemNode.classList.add("parent");
        else {
            this._listItemNode.classList.remove("parent");
            this.collapse();
        }

        this.didChange();
    }

    get hidden()
    {
        return this._hidden;
    }

    set hidden(x)
    {
        if (this._hidden === x)
            return;

        this._hidden = x;

        if (this._listItemNode)
            this._listItemNode.hidden = this._hidden;
        if (this._childrenListNode)
            this._childrenListNode.hidden = this._hidden;

        if (this.treeOutline) {
            if (this.treeOutline.virtualized)
                this.treeOutline.updateVirtualizedElementsDebouncer.delayForFrame();

            this.treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementVisibilityDidChange, {element: this});
        }
    }

    get shouldRefreshChildren()
    {
        return this._shouldRefreshChildren;
    }

    set shouldRefreshChildren(x)
    {
        this._shouldRefreshChildren = x;
        if (x && this.expanded)
            this.expand();
    }

    get previousSelectableSibling()
    {
        let treeElement = this.previousSibling;
        while (treeElement && !treeElement.selectable)
            treeElement = treeElement.previousSibling;
        return treeElement;
    }

    get nextSelectableSibling()
    {
        let treeElement = this.nextSibling;
        while (treeElement && !treeElement.selectable)
            treeElement = treeElement.nextSibling;
        return treeElement;
    }

    canSelectOnMouseDown(event)
    {
        // Overridden by subclasses if needed.
        return true;
    }

    _fireDidChange()
    {
        if (this.treeOutline)
            this.treeOutline._treeElementDidChange(this);
    }

    didChange()
    {
        if (!this.treeOutline)
            return;

        if (!this._fireDidChangeDebouncer) {
            this._fireDidChangeDebouncer = new Debouncer(() => {
                this._fireDidChange();
            });
        }

        this._fireDidChangeDebouncer.delayForFrame();
    }

    _setListItemNodeContent()
    {
        if (!this._listItemNode)
            return;

        if (!this._titleHTML && !this._title)
            this._listItemNode.removeChildren();
        else if (typeof this._titleHTML === "string")
            this._listItemNode.innerHTML = this._titleHTML;
        else if (typeof this._title === "string")
            this._listItemNode.textContent = this._title;
        else {
            this._listItemNode.removeChildren();
            if (this._title.parentNode)
                this._title.parentNode.removeChild(this._title);
            this._listItemNode.appendChild(this._title);
        }
    }

    _attach()
    {
        if (!this._listItemNode || this.parent._shouldRefreshChildren) {
            if (this._listItemNode && this._listItemNode.parentNode)
                this._listItemNode.parentNode.removeChild(this._listItemNode);

            this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
            this._listItemNode.treeElement = this;
            this._setListItemNodeContent();
            this._listItemNode.title = this._tooltip ? this._tooltip : "";
            this._listItemNode.hidden = this.hidden;
            this._listItemNode.role = "treeitem";

            if (this.hasChildren)
                this._listItemNode.classList.add("parent");
            if (this.expanded)
                this._listItemNode.classList.add("expanded");
            if (this.selected)
                this._listItemNode.classList.add("selected");

            this._listItemNode.addEventListener("click", WI.TreeElement.treeElementToggled);
            this._listItemNode.addEventListener("dblclick", WI.TreeElement.treeElementDoubleClicked);

            if (this.onattach)
                this.onattach(this);
        }

        var nextSibling = null;
        if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
            nextSibling = this.nextSibling._listItemNode;

        if (!this.treeOutline || !this.treeOutline.virtualized) {
            this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
            if (this._childrenListNode)
                this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
        }

        if (this.selected)
            this.select();
        if (this.expanded)
            this.expand();
    }

    _detach()
    {
        if (this.ondetach)
            this.ondetach(this);
        if (this._listItemNode && this._listItemNode.parentNode)
            this._listItemNode.parentNode.removeChild(this._listItemNode);
        if (this._childrenListNode && this._childrenListNode.parentNode)
            this._childrenListNode.parentNode.removeChild(this._childrenListNode);
    }

    static treeElementToggled(event)
    {
        let element = event.currentTarget;
        if (!element)
            return;

        let treeElement = element.treeElement;
        if (!treeElement)
            return;

        let toggleOnClick = treeElement.toggleOnClick && !treeElement.selectable;
        if (toggleOnClick || treeElement.isEventWithinDisclosureTriangle(event)) {
            if (treeElement.expanded) {
                if (event.altKey)
                    treeElement.collapseRecursively();
                else
                    treeElement.collapse();
            } else {
                if (event.altKey)
                    treeElement.expandRecursively();
                else
                    treeElement.expand();
            }
            event.stopPropagation();
        }

        if (!treeElement.treeOutline.selectable)
            treeElement.treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementClicked, {treeElement});
    }

    static treeElementDoubleClicked(event)
    {
        var element = event.currentTarget;
        if (!element || !element.treeElement)
            return;

        if (element.treeElement.isEventWithinDisclosureTriangle(event))
            return;

        if (element.treeElement.dispatchEventToListeners(WI.TreeElement.Event.DoubleClick))
            return;

        if (element.treeElement.ondblclick)
            element.treeElement.ondblclick.call(element.treeElement, event);
        else if (element.treeElement.hasChildren && !element.treeElement.expanded)
            element.treeElement.expand();
    }

    collapse()
    {
        if (this._listItemNode) {
            this._listItemNode.classList.remove("expanded");
            this._listItemNode.ariaExpanded = false;
        }
        if (this._childrenListNode) {
            this._childrenListNode.classList.remove("expanded");
            this._childrenListNode.ariaExpanded = false;
        }

        this.expanded = false;
        if (this.treeOutline)
            this.treeOutline._treeElementsExpandedState[this.identifier] = false;

        if (this.oncollapse)
            this.oncollapse(this);

        if (this.treeOutline) {
            if (this.treeOutline.virtualized)
                this.treeOutline.updateVirtualizedElementsDebouncer.delayForFrame();

            this.treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
        }
    }

    collapseRecursively()
    {
        var item = this;
        while (item) {
            if (item.expanded)
                item.collapse();
            item = item.traverseNextTreeElement(false, this, true);
        }
    }

    expand()
    {
        if (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)
            return;

        // Set this before onpopulate. Since onpopulate can add elements and dispatch an ElementAdded event,
        // this makes sure the expanded flag is true before calling those functions. This prevents the
        // possibility of an infinite loop if onpopulate or an event handler were to call expand.

        this.expanded = true;
        if (this.treeOutline)
            this.treeOutline._treeElementsExpandedState[this.identifier] = true;

        // If there are no children, return. We will be expanded once we have children.
        if (!this.hasChildren)
            return;

        if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
            if (this._childrenListNode && this._childrenListNode.parentNode)
                this._childrenListNode.parentNode.removeChild(this._childrenListNode);

            this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
            this._childrenListNode.parentTreeElement = this;
            this._childrenListNode.classList.add("children");
            this._childrenListNode.hidden = this.hidden;
            this._childrenListNode.role = "group";

            this.onpopulate();

            // It is necessary to set expanded to true again here because some subclasses will call
            // collapse in onpopulate (via removeChildren), which sets it back to false.
            this.expanded = true;

            for (var i = 0; i < this.children.length; ++i)
                this.children[i]._attach();

            this._shouldRefreshChildren = false;
        }

        if (this._listItemNode) {
            this._listItemNode.classList.add("expanded");
            this._listItemNode.ariaExpanded = true;

            if (this._childrenListNode && this._childrenListNode.parentNode !== this._listItemNode.parentNode)
                this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
        }

        if (this._childrenListNode) {
            this._childrenListNode.classList.add("expanded");
            this._childrenListNode.ariaExpanded = true;
        }

        if (this.onexpand)
            this.onexpand(this);

        if (this.treeOutline) {
            if (this.treeOutline.virtualized)
                this.treeOutline.updateVirtualizedElementsDebouncer.delayForFrame();

            this.treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
        }
    }

    expandRecursively(maxDepth)
    {
        var item = this;
        var info = {};
        var depth = 0;

        // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
        // in some case can be infinite, since JavaScript objects can hold circular references.
        // So default to a recursion cap of 3 levels, since that gives fairly good results.
        if (maxDepth === undefined)
            maxDepth = 3;

        while (item) {
            if (depth < maxDepth)
                item.expand();
            item = item.traverseNextTreeElement(false, this, depth >= maxDepth, info);
            depth += info.depthChange;
        }
    }

    hasAncestor(ancestor)
        {
        if (!ancestor)
            return false;

        var currentNode = this.parent;
        while (currentNode) {
            if (ancestor === currentNode)
                return true;
            currentNode = currentNode.parent;
        }

        return false;
    }

    reveal()
    {
        var currentAncestor = this.parent;
        while (currentAncestor && !currentAncestor.root) {
            if (!currentAncestor.expanded)
                currentAncestor.expand();
            currentAncestor = currentAncestor.parent;
        }

        // This must be called before onreveal, as some subclasses will scrollIntoViewIfNeeded and
        // we should update the visible elements before attempting to scroll.
        if (this.treeOutline && this.treeOutline.virtualized)
            this.treeOutline.updateVirtualizedElementsDebouncer.force(this);

        if (this.onreveal)
            this.onreveal(this);

        if (this.treeOutline)
            this.treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.ElementRevealed, {element: this});
    }

    revealed(ignoreHidden)
    {
        if (!ignoreHidden && this.hidden)
            return false;

        var currentAncestor = this.parent;
        while (currentAncestor && !currentAncestor.root) {
            if (!currentAncestor.expanded)
                return false;
            if (!ignoreHidden && currentAncestor.hidden)
                return false;
            currentAncestor = currentAncestor.parent;
        }

        return true;
    }

    select(omitFocus, selectedByUser, suppressNotification)
    {
        let treeOutline = this.treeOutline;
        if (!treeOutline || !this.selectable)
            return;

        if (!omitFocus)
            this.focus();
        else if (treeOutline.element.contains(document.activeElement)) {
            // When treeOutline has focus, focus on the newly selected treeElement.
            this.focus();
        }

        if (this.selected && !this.treeOutline.allowsRepeatSelection)
            return;

        // Focusing on another node may detach "this" from tree.
        treeOutline = this.treeOutline;
        if (!treeOutline)
            return;

        this.selected = true;
        treeOutline.selectTreeElementInternal(this, suppressNotification, selectedByUser);

        if (this._listItemNode)
            this._listItemNode.ariaSelected = true;
    }

    revealAndSelect(omitFocus, selectedByUser, suppressNotification)
    {
        this.reveal();
        this.select(omitFocus, selectedByUser, suppressNotification);
    }

    deselect(suppressNotification)
    {
        if (!this.treeOutline || !this.selected)
            return false;

        this.selected = false;
        this.treeOutline.selectTreeElementInternal(null, suppressNotification);

        if (this._listItemNode) {
            this.unfocus();
            this._listItemNode.ariaSelected = false;
        }

        return true;
    }

    focus()
    {
        if (!this._listItemNode)
            return;

        this._listItemNode.tabIndex = 0;
        this._listItemNode.focus();
    }

    unfocus()
    {
        if (!this._listItemNode)
            return;

        this._listItemNode.removeAttribute("tabIndex");
    }

    onpopulate()
    {
        // Overridden by subclasses.
    }

    traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate, info)
    {
        function shouldSkip(element) {
            return skipUnrevealed && !element.revealed(true);
        }

        var depthChange = 0;
        var element = this;

        if (!dontPopulate)
            element.onpopulate();

        do {
            if (element.hasChildren && element.children[0] && (!skipUnrevealed || element.expanded)) {
                element = element.children[0];
                depthChange += 1;
            } else {
                while (element && !element.nextSibling && element.parent && !element.parent.root && element.parent !== stayWithin) {
                    element = element.parent;
                    depthChange -= 1;
                }

                if (element)
                    element = element.nextSibling;
            }
        } while (element && shouldSkip(element));

        if (info)
            info.depthChange = depthChange;

        return element;
    }

    traversePreviousTreeElement(skipUnrevealed, dontPopulate)
    {
        function shouldSkip(element) {
            return skipUnrevealed && !element.revealed(true);
        }

        var element = this;

        do {
            if (element.previousSibling) {
                element = element.previousSibling;

                while (element && element.hasChildren && element.expanded && !shouldSkip(element)) {
                    if (!dontPopulate)
                        element.onpopulate();
                    element = element.children.lastValue;
                }
            } else
                element = element.parent && element.parent.root ? null : element.parent;
        } while (element && shouldSkip(element));

        return element;
    }

    isEventWithinDisclosureTriangle(event)
    {
        if (!document.contains(this._listItemNode))
            return false;

        // FIXME: We should not use getComputedStyle(). For that we need to get rid of using ::before for disclosure triangle. (http://webk.it/74446)
        let computedStyle = window.getComputedStyle(this._listItemNode);
        let start = 0;
        if (computedStyle.direction === WI.LayoutDirection.RTL)
            start += this._listItemNode.totalOffsetRight - computedStyle.getPropertyCSSValue("padding-right").getFloatValue(CSSPrimitiveValue.CSS_PX) - this.arrowToggleWidth;
        else
            start += this._listItemNode.totalOffsetLeft + computedStyle.getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);

        return event.pageX >= start && event.pageX <= start + this.arrowToggleWidth && this.hasChildren;
    }

    populateContextMenu(contextMenu, event)
    {
        if (this.children.some((child) => child.hasChildren) || (this.hasChildren && !this.children.length)) {
            contextMenu.appendSeparator();

            contextMenu.appendItem(WI.UIString("Expand All"), this.expandRecursively.bind(this));
            contextMenu.appendItem(WI.UIString("Collapse All"), this.collapseRecursively.bind(this));
        }
    }
};

WI.TreeElement.Event = {
    DoubleClick: "tree-element-double-click",
};
