/*
 * 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;

            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");
        if (this._childrenListNode)
            this._childrenListNode.classList.remove("expanded");

        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.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");
            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");

        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)
    {
        if (!this.treeOutline || !this.selectable)
            return;

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

        if (!omitFocus)
            this.treeOutline._childrenListNode.focus();

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

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

    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);

        return true;
    }

    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",
};
