/*
 * Copyright (C) 2008, 2013-2017 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.DataGridNode = class DataGridNode extends WI.Object
{
    constructor(data, hasChildren, classNames)
    {
        super();

        this._expanded = false;
        this._hidden = false;
        this._selected = false;
        this._copyable = true;
        this._editable = true;
        this._shouldRefreshChildren = true;
        this._data = data || {};
        this.hasChildren = hasChildren || false;
        this.children = [];
        this.dataGrid = null;
        this.parent = null;
        this.previousSibling = null;
        this.nextSibling = null;
        this.disclosureToggleWidth = 10;
        this._classNames = classNames || [];
    }

    get hidden()
    {
        return this._hidden;
    }

    set hidden(x)
    {
        x = !!x;

        if (this._hidden === x)
            return;

        this._hidden = x;
        if (this._element)
            this._element.classList.toggle("hidden", this._hidden);

        if (this.dataGrid)
            this.dataGrid._noteRowsChanged();
    }

    get selectable()
    {
        return this._element && !this._hidden;
    }

    get copyable()
    {
        return this._copyable;
    }

    set copyable(x)
    {
        this._copyable = x;
    }

    get editable()
    {
        return this._editable;
    }

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

    get element()
    {
        if (this._element)
            return this._element;

        if (!this.dataGrid)
            return null;

        this._element = document.createElement("tr");
        this._element._dataGridNode = this;

        if (this.hasChildren)
            this._element.classList.add("parent");
        if (this.expanded)
            this._element.classList.add("expanded");
        if (this.selected)
            this._element.classList.add("selected");
        if (this.revealed)
            this._element.classList.add("revealed");
        if (this._hidden)
            this._element.classList.add("hidden");
        this._element.classList.add(...this._classNames);

        this.createCells();
        return this._element;
    }

    createCells()
    {
        for (var columnIdentifier of this.dataGrid.orderedColumns)
            this._element.appendChild(this.createCell(columnIdentifier));
    }

    refreshIfNeeded()
    {
        if (!this._needsRefresh)
            return;

        this._needsRefresh = false;

        this.refresh();
    }

    needsRefresh()
    {
        this._needsRefresh = true;

        if (!this._revealed)
            return;

        if (this._scheduledRefreshIdentifier)
            return;

        this._scheduledRefreshIdentifier = requestAnimationFrame(this.refresh.bind(this));
    }

    get data()
    {
        return this._data;
    }

    set data(x)
    {
        console.assert(typeof x === "object", "Data should be an object.");

        x = x || {};

        if (Object.shallowEqual(this._data, x))
            return;

        this._data = x;
        this.needsRefresh();
    }

    get filterableData()
    {
        if (this._cachedFilterableData)
            return this._cachedFilterableData;

        this._cachedFilterableData = [];

        for (let column of this.dataGrid.columns.values()) {
            if (column.hidden)
                continue;

            let value = this.filterableDataForColumn(column.columnIdentifier);
            if (!value)
                continue;

            if (!(value instanceof Array))
                value = [value];

            if (!value.length)
                continue;

            this._cachedFilterableData.pushAll(value);
        }

        return this._cachedFilterableData;
    }

    get revealed()
    {
        if ("_revealed" in this)
            return this._revealed;

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

            currentAncestor = currentAncestor.parent;
        }

        this._revealed = true;
        return true;
    }

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

        this._hasChildren = x;

        if (!this._element)
            return;

        if (this._hasChildren) {
            this._element.classList.add("parent");
            if (this.expanded)
                this._element.classList.add("expanded");
        } else
            this._element.classList.remove("parent", "expanded");
    }

    get hasChildren()
    {
        return this._hasChildren;
    }

    set revealed(x)
    {
        if (this._revealed === x)
            return;

        this._revealed = x;

        if (this._element) {
            if (this._revealed)
                this._element.classList.add("revealed");
            else
                this._element.classList.remove("revealed");
        }

        this.refreshIfNeeded();

        for (var i = 0; i < this.children.length; ++i)
            this.children[i].revealed = x && this.expanded;
    }

    get depth()
    {
        if ("_depth" in this)
            return this._depth;
        if (this.parent && !this.parent.root)
            this._depth = this.parent.depth + 1;
        else
            this._depth = 0;
        return this._depth;
    }

    get indentPadding()
    {
        if (typeof this._indentPadding === "number")
            return this._indentPadding;

        this._indentPadding = this.depth * this.dataGrid.indentWidth;
        return this._indentPadding;
    }

    get shouldRefreshChildren()
    {
        return this._shouldRefreshChildren;
    }

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

    get selected()
    {
        return this._selected;
    }

    set selected(x)
    {
        if (x)
            this.select();
        else
            this.deselect();
    }

    get expanded()
    {
        return this._expanded;
    }

    set expanded(x)
    {
        if (x)
            this.expand();
        else
            this.collapse();
    }

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

        let currentAncestor = this.parent;
        while (currentAncestor) {
            if (ancestor === currentAncestor)
                return true;

            currentAncestor = currentAncestor.parent;
        }

        return false;
    }

    refresh()
    {
        if (!this._element || !this.dataGrid)
            return;

        if (this._scheduledRefreshIdentifier) {
            cancelAnimationFrame(this._scheduledRefreshIdentifier);
            this._scheduledRefreshIdentifier = undefined;
        }

        this._cachedFilterableData = null;
        this._needsRefresh = false;

        this._element.removeChildren();
        this.createCells();
    }

    refreshRecursively()
    {
        this.refresh();
        this.forEachChildInSubtree((node) => node.refresh());
    }

    updateLayout()
    {
        // Implemented by subclasses if needed.
    }

    createCell(columnIdentifier)
    {
        var cellElement = document.createElement("td");
        cellElement.className = columnIdentifier + "-column";
        cellElement.__columnIdentifier = columnIdentifier;

        var div = cellElement.createChild("div", "cell-content");
        var content = this.createCellContent(columnIdentifier, cellElement);
        div.append(content);

        let column = this.dataGrid.columns.get(columnIdentifier);
        if (column) {
            if (column["aligned"])
                cellElement.classList.add(column["aligned"]);

            if (column["group"])
                cellElement.classList.add("column-group-" + column["group"]);

            if (column["icon"]) {
                let iconElement = document.createElement("div");
                iconElement.classList.add("icon");
                div.insertBefore(iconElement, div.firstChild);
            }
        }

        if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
            cellElement.classList.add("disclosure");
            if (this.indentPadding) {
                if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL)
                    cellElement.style.setProperty("padding-right", `${this.indentPadding}px`);
                else
                    cellElement.style.setProperty("padding-left", `${this.indentPadding}px`);
            }
        }

        return cellElement;
    }

    createCellContent(columnIdentifier)
    {
        if (!(columnIdentifier in this.data))
            return zeroWidthSpace; // Zero width space to keep the cell from collapsing.

        let data = this.data[columnIdentifier];
        return typeof data === "number" ? data.maxDecimals(2).toLocaleString() : data;
    }

    elementWithColumnIdentifier(columnIdentifier)
    {
        if (!this.dataGrid)
            return null;

        let index = this.dataGrid.orderedColumns.indexOf(columnIdentifier);
        if (index === -1)
            return null;

        return this.element.children[index];
    }

    // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
    appendChild() { return WI.DataGrid.prototype.appendChild.apply(this, arguments); }
    insertChild() { return WI.DataGrid.prototype.insertChild.apply(this, arguments); }
    removeChild() { return WI.DataGrid.prototype.removeChild.apply(this, arguments); }
    removeChildren() { return WI.DataGrid.prototype.removeChildren.apply(this, arguments); }

    _recalculateSiblings(myIndex)
    {
        if (!this.parent)
            return;

        var previousChild = myIndex > 0 ? this.parent.children[myIndex - 1] : null;

        if (previousChild) {
            previousChild.nextSibling = this;
            this.previousSibling = previousChild;
        } else
            this.previousSibling = null;

        var nextChild = this.parent.children[myIndex + 1];

        if (nextChild) {
            nextChild.previousSibling = this;
            this.nextSibling = nextChild;
        } else
            this.nextSibling = null;
    }

    collapse()
    {
        if (this._element)
            this._element.classList.remove("expanded");

        this._expanded = false;

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

        this.dispatchEventToListeners("collapsed");

        if (this.dataGrid) {
            this.dataGrid.dispatchEventToListeners(WI.DataGrid.Event.CollapsedNode, {dataGridNode: this});
            this.dataGrid._noteRowsChanged();
        }
    }

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

    expand()
    {
        if (!this.hasChildren || this.expanded)
            return;

        if (this.revealed && !this._shouldRefreshChildren)
            for (var i = 0; i < this.children.length; ++i)
                this.children[i].revealed = true;

        if (this._shouldRefreshChildren) {
            for (var i = 0; i < this.children.length; ++i)
                this.children[i]._detach();

            this.dispatchEventToListeners("populate");

            if (this._attached) {
                for (var i = 0; i < this.children.length; ++i) {
                    var child = this.children[i];
                    if (this.revealed)
                        child.revealed = true;
                    child._attach();
                }
            }

            this._shouldRefreshChildren = false;
        }

        if (this._element)
            this._element.classList.add("expanded");

        this._expanded = true;

        this.dispatchEventToListeners("expanded");

        if (this.dataGrid) {
            this.dataGrid.dispatchEventToListeners(WI.DataGrid.Event.ExpandedNode, {dataGridNode: this});
            this.dataGrid._noteRowsChanged();
        }
    }

    expandRecursively()
    {
        var item = this;
        while (item) {
            item.expand();
            item = item.traverseNextNode(false, this);
        }
    }

    forEachImmediateChild(callback)
    {
        for (let node of this.children)
            callback(node);
    }

    forEachChildInSubtree(callback)
    {
        let node = this.traverseNextNode(false, this, true);
        while (node) {
            callback(node);
            node = node.traverseNextNode(false, this, true);
        }
    }

    isInSubtreeOfNode(baseNode)
    {
        let node = baseNode;
        while (node) {
            if (node === this)
                return true;
            node = node.traverseNextNode(false, baseNode, true);
        }
        return false;
    }

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

        this.dataGrid.updateVisibleRows(this);

        this.dispatchEventToListeners("revealed");
    }

    select(suppressSelectedEvent)
    {
        if (!this.dataGrid || !this.selectable || this.selected)
            return;

        let oldSelectedNode = this.dataGrid.selectedNode;
        if (oldSelectedNode)
            oldSelectedNode.deselect(true);

        this._selected = true;
        this.dataGrid.selectedNode = this;

        if (this._element)
            this._element.classList.add("selected");

        if (!suppressSelectedEvent)
            this.dataGrid.dispatchEventToListeners(WI.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode});
    }

    revealAndSelect(suppressSelectedEvent)
    {
        this.reveal();
        this.select(suppressSelectedEvent);
    }

    deselect(suppressDeselectedEvent)
    {
        if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
            return;

        this._selected = false;
        this.dataGrid.selectedNode = null;

        if (this._element)
            this._element.classList.remove("selected");

        if (!suppressDeselectedEvent)
            this.dataGrid.dispatchEventToListeners(WI.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode: this});
    }

    traverseNextNode(skipHidden, stayWithin, dontPopulate, info)
    {
        if (!dontPopulate && this.hasChildren)
            this.dispatchEventToListeners("populate");

        if (info)
            info.depthChange = 0;

        var node = (!skipHidden || this.revealed) ? this.children[0] : null;
        if (node && (!skipHidden || this.expanded)) {
            if (info)
                info.depthChange = 1;
            return node;
        }

        if (this === stayWithin)
            return null;

        node = (!skipHidden || this.revealed) ? this.nextSibling : null;
        if (node)
            return node;

        node = this;
        while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
            if (info)
                info.depthChange -= 1;
            node = node.parent;
        }

        if (!node)
            return null;

        return (!skipHidden || node.revealed) ? node.nextSibling : null;
    }

    traversePreviousNode(skipHidden, dontPopulate)
    {
        var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
        if (!dontPopulate && node && node.hasChildren)
            node.dispatchEventToListeners("populate");

        while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null)) {
            if (!dontPopulate && node.hasChildren)
                node.dispatchEventToListeners("populate");
            node = (!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null;
        }

        if (node)
            return node;

        if (!this.parent || this.parent.root)
            return null;

        return this.parent;
    }

    isEventWithinDisclosureTriangle(event)
    {
        if (!this.hasChildren)
            return false;

        let cell = event.target.closest("td");
        if (!cell || !cell.classList.contains("disclosure"))
            return false;

        let computedStyle = window.getComputedStyle(cell);
        let start = 0;
        if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL)
            start += cell.totalOffsetRight - computedStyle.getPropertyCSSValue("padding-right").getFloatValue(CSSPrimitiveValue.CSS_PX) - this.disclosureToggleWidth;
        else
            start += cell.totalOffsetLeft + computedStyle.getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
        return event.pageX >= start && event.pageX <= start + this.disclosureToggleWidth;
    }

    _attach()
    {
        if (!this.dataGrid || this._attached)
            return;

        this._attached = true;

        let insertionIndex = -1;

        if (!this.isPlaceholderNode) {
            var previousGridNode = this.traversePreviousNode(true, true);
            insertionIndex = this.dataGrid._rows.indexOf(previousGridNode);
            if (insertionIndex === -1)
                insertionIndex = 0;
            else
                insertionIndex++;
        }

        if (insertionIndex === -1)
            this.dataGrid._rows.push(this);
        else
            this.dataGrid._rows.insertAtIndex(this, insertionIndex);

        this.dataGrid._noteRowsChanged();

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

    _detach()
    {
        if (!this._attached)
            return;

        this._attached = false;

        this.dataGrid._rows.remove(this, true);
        this.dataGrid._noteRowRemoved(this);

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

    savePosition()
    {
        if (this._savedPosition)
            return;

        console.assert(this.parent);
        if (!this.parent)
            return;

        this._savedPosition = {
            parent: this.parent,
            index: this.parent.children.indexOf(this)
        };
    }

    restorePosition()
    {
        if (!this._savedPosition)
            return;

        if (this.parent !== this._savedPosition.parent)
            this._savedPosition.parent.insertChild(this, this._savedPosition.index);

        this._savedPosition = null;
    }

    appendContextMenuItems(contextMenu)
    {
        // Subclasses may override
        return null;
    }

    // Protected

    filterableDataForColumn(columnIdentifier)
    {
        let value = this.data[columnIdentifier];
        return typeof value === "string" ? value : null;
    }

    didResizeColumn(columnIdentifier)
    {
        // Override by subclasses.
    }
};

// Used to create a new table row when entering new data by editing cells.
WI.PlaceholderDataGridNode = class PlaceholderDataGridNode extends WI.DataGridNode
{
    constructor(data)
    {
        super(data, false);
        this.isPlaceholderNode = true;
    }

    makeNormal()
    {
        this.isPlaceholderNode = false;
    }
};
