/*
 * 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, {selectable, copyable, editable, hasChildren, classNames} = {})
    {
        super();

        this._expanded = false;
        this._hidden = false;
        this._selected = false;
        this._selectable = selectable !== undefined ? selectable : true;
        this._copyable = copyable !== undefined ? copyable : true;
        this._editable = editable !== undefined ? 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 && this._selectable;
    }

    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");
                iconElement.title = this.generateIconTitle(columnIdentifier);
                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;
    }

    generateIconTitle(columnIdentifier)
    {
        // Overridden by subclasses if needed.
        return "";
    }

    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;

        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(DataGridNode.Event.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;

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

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

        this._selected = true;
        this._element?.classList.add("selected");

        this.dataGrid.selectDataGridNodeInternal(this, suppressSelectedEvent);
    }

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

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

        this._selected = false;
        this._element?.classList.remove("selected");

        this.dataGrid.deselectDataGridNodeInternal(this, suppressDeselectedEvent);
    }

    traverseNextNode(skipHidden, stayWithin, dontPopulate, info)
    {
        if (!dontPopulate && this.hasChildren)
            this.dispatchEventToListeners(DataGridNode.Event.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(DataGridNode.Event.Populate);

        while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null)) {
            if (!dontPopulate && node.hasChildren)
                node.dispatchEventToListeners(DataGridNode.Event.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.
    }
};

WI.DataGridNode.Event = {
    Populate: "data-grid-node-populate",
};

// 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);
        this.isPlaceholderNode = true;
    }

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