/*
 * Copyright (C) 2014, 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.
 *
 * 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.TimelineDataGridNode = class TimelineDataGridNode extends WI.DataGridNode
{
    constructor(records, options = {})
    {
        super({}, options.hasChildren);

        this.copyable = false;

        this._records = records;
        this._includesGraph = options.includesGraph || false;
        this._graphDataSource = options.graphDataSource || null;
        this._cachedData = null;

        if (this._graphDataSource) {
            this._graphContainerElement = document.createElement("div");
            this._timelineRecordBars = [];
        }
    }

    // Public

    get records() { return this._records; }

    get record()
    {
        return this.records && this.records.length ? this.records[0] : null;
    }

    get graphDataSource()
    {
        return this._graphDataSource;
    }

    get data()
    {
        if (!this._graphDataSource)
            return {};

        return {
            graph: this.record ? this.record.startTime : 0,
        };
    }

    collapse()
    {
        super.collapse();

        if (!this._graphDataSource || !this.revealed)
            return;

        // Refresh to show child bars in our graph now that we collapsed.
        this.refreshGraph();
    }

    expand()
    {
        super.expand();

        if (!this._graphDataSource || !this.revealed)
            return;

        // Refresh to remove child bars from our graph now that we expanded.
        this.refreshGraph();

        // Refresh child graphs since they haven't been updating while we were collapsed.
        var childNode = this.children[0];
        while (childNode) {
            if (childNode instanceof WI.TimelineDataGridNode)
                childNode.refreshGraph();
            childNode = childNode.traverseNextNode(true, this);
        }
    }

    createCellContent(columnIdentifier, cell)
    {
        if (columnIdentifier === "graph" && this._graphDataSource) {
            this.needsGraphRefresh();
            return this._graphContainerElement;
        }

        var value = this.data[columnIdentifier];
        if (!value)
            return emDash;

        const options = {
            useGoToArrowButton: true,
            ignoreNetworkTab: true,
            ignoreSearchTab: true,
        };

        if (value instanceof WI.SourceCodeLocation) {
            if (value.sourceCode instanceof WI.Resource) {
                cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName, ...WI.Resource.classNamesForResource(value.sourceCode));
            } else if (value.sourceCode instanceof WI.Script) {
                if (value.sourceCode.url) {
                    cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName);
                    cell.classList.add(WI.Resource.Type.Script);
                } else
                    cell.classList.add(WI.ScriptTreeElement.AnonymousScriptIconStyleClassName);
            } else
                console.error("Unknown SourceCode subclass.");

            // Give the whole cell a tooltip and keep it up to date.
            value.populateLiveDisplayLocationTooltip(cell);

            var fragment = document.createDocumentFragment();
            fragment.appendChild(WI.createSourceCodeLocationLink(value, options));

            var titleElement = document.createElement("span");
            value.populateLiveDisplayLocationString(titleElement, "textContent");
            fragment.appendChild(titleElement);

            return fragment;
        }

        if (value instanceof WI.CallFrame) {
            var callFrame = value;

            var isAnonymousFunction = false;
            var functionName = callFrame.functionName;
            if (!functionName) {
                functionName = WI.UIString("(anonymous function)");
                isAnonymousFunction = true;
            }

            cell.classList.add(WI.CallFrameView.FunctionIconStyleClassName);

            var fragment = document.createDocumentFragment();

            if (callFrame.sourceCodeLocation && callFrame.sourceCodeLocation.sourceCode) {
                // Give the whole cell a tooltip and keep it up to date.
                callFrame.sourceCodeLocation.populateLiveDisplayLocationTooltip(cell);

                fragment.appendChild(WI.createSourceCodeLocationLink(callFrame.sourceCodeLocation, options));

                if (isAnonymousFunction) {
                    // For anonymous functions we show the resource or script icon and name.
                    if (callFrame.sourceCodeLocation.sourceCode instanceof WI.Resource) {
                        cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName, ...WI.Resource.classNamesForResource(callFrame.sourceCodeLocation.sourceCode));
                    } else if (callFrame.sourceCodeLocation.sourceCode instanceof WI.Script) {
                        if (callFrame.sourceCodeLocation.sourceCode.url) {
                            cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName);
                            cell.classList.add(WI.Resource.Type.Script);
                        } else
                            cell.classList.add(WI.ScriptTreeElement.AnonymousScriptIconStyleClassName);
                    } else
                        console.error("Unknown SourceCode subclass.");

                    var titleElement = document.createElement("span");
                    callFrame.sourceCodeLocation.populateLiveDisplayLocationString(titleElement, "textContent");

                    fragment.appendChild(titleElement);
                } else {
                    // Show the function name and icon.
                    cell.classList.add(WI.CallFrameView.FunctionIconStyleClassName);

                    fragment.append(functionName);

                    var subtitleElement = document.createElement("span");
                    subtitleElement.classList.add("subtitle");
                    callFrame.sourceCodeLocation.populateLiveDisplayLocationString(subtitleElement, "textContent");

                    fragment.appendChild(subtitleElement);
                }

                return fragment;
            }

            var icon = document.createElement("div");
            icon.classList.add("icon");

            fragment.append(icon, functionName);

            return fragment;
        }

        if (value instanceof WI.DOMNode) {
            cell.classList.add(WI.DOMTreeElementPathComponent.iconClassNameForNode(value));
            return WI.linkifyNodeReference(value);
        }

        return super.createCellContent(columnIdentifier, cell);
    }

    refresh()
    {
        this._cachedData = null;

        if (this._graphDataSource && this._includesGraph)
            this.needsGraphRefresh();

        super.refresh();
    }

    refreshGraph()
    {
        if (!this._graphDataSource)
            return;

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

        // We are not visible, but an ancestor will draw our graph.
        // They need notified by using our needsGraphRefresh.
        console.assert(this.revealed);
        if (!this.revealed)
            return;

        let secondsPerPixel = this._graphDataSource.secondsPerPixel;
        if (isNaN(secondsPerPixel))
            return;

        console.assert(secondsPerPixel > 0);

        var recordBarIndex = 0;

        function createBar(records, renderMode)
        {
            var timelineRecordBar = this._timelineRecordBars[recordBarIndex];
            if (!timelineRecordBar)
                timelineRecordBar = this._timelineRecordBars[recordBarIndex] = new WI.TimelineRecordBar(this, records, renderMode);
            else {
                timelineRecordBar.renderMode = renderMode;
                timelineRecordBar.records = records;
            }
            timelineRecordBar.refresh(this._graphDataSource);
            if (!timelineRecordBar.element.parentNode) {
                this._graphContainerElement.appendChild(timelineRecordBar.element);
                this.didAddRecordBar(timelineRecordBar);
            }
            ++recordBarIndex;
        }

        function collectRecordsByType(records, recordsByTypeMap)
        {
            for (var record of records) {
                var typedRecords = recordsByTypeMap.get(record.type);
                if (!typedRecords) {
                    typedRecords = [];
                    recordsByTypeMap.set(record.type, typedRecords);
                }

                typedRecords.push(record);
            }
        }

        var boundCreateBar = createBar.bind(this);

        if (this.expanded) {
            // When expanded just use the records for this node.
            WI.TimelineRecordBar.createCombinedBars(this.records, secondsPerPixel, this._graphDataSource, boundCreateBar);
        } else {
            // When collapsed use the records for this node and its descendants.
            // To share bars better, group records by type.

            var recordTypeMap = new Map;
            collectRecordsByType(this.records, recordTypeMap);

            var childNode = this.children[0];
            while (childNode) {
                if (childNode instanceof WI.TimelineDataGridNode)
                    collectRecordsByType(childNode.records, recordTypeMap);
                childNode = childNode.traverseNextNode(false, this);
            }

            for (var records of recordTypeMap.values())
                WI.TimelineRecordBar.createCombinedBars(records, secondsPerPixel, this._graphDataSource, boundCreateBar);
        }

        // Remove the remaining unused TimelineRecordBars.
        for (; recordBarIndex < this._timelineRecordBars.length; ++recordBarIndex) {
            this._timelineRecordBars[recordBarIndex].element.remove();
            this.didRemoveRecordBar(this._timelineRecordBars[recordBarIndex]);
            this._timelineRecordBars[recordBarIndex].records = null;
        }
    }

    needsGraphRefresh()
    {
        if (!this.revealed) {
            // We are not visible, but an ancestor will be drawing our graph.
            // Notify the next visible ancestor that their graph needs to refresh.
            var ancestor = this;
            while (ancestor && !ancestor.root) {
                if (ancestor.revealed && ancestor instanceof WI.TimelineDataGridNode) {
                    ancestor.needsGraphRefresh();
                    return;
                }

                ancestor = ancestor.parent;
            }

            return;
        }

        if (!this._graphDataSource || this._scheduledGraphRefreshIdentifier)
            return;

        this._scheduledGraphRefreshIdentifier = requestAnimationFrame(this.refreshGraph.bind(this));
    }

    displayName()
    {
        // Can be overridden by subclasses.
        const includeDetailsInMainTitle = true;
        return WI.TimelineTabContentView.displayNameForRecord(this.record, includeDetailsInMainTitle);
    }

    iconClassNames()
    {
        // Can be overridden by subclasses.
        return [WI.TimelineTabContentView.iconClassNameForRecord(this.record)];
    }

    // Protected

    createGoToArrowButton(cellElement, callback)
    {
        function buttonClicked(event)
        {
            if (this.hidden || !this.revealed)
                return;

            event.stopPropagation();

            callback(this, cellElement.__columnIdentifier);
        }

        let button = WI.createGoToArrowButton();
        button.addEventListener("click", buttonClicked.bind(this));

        let contentElement = cellElement.firstChild;
        contentElement.appendChild(button);
    }

    isRecordVisible(record)
    {
        if (!this._graphDataSource)
            return false;

        if (isNaN(record.startTime))
            return false;

        // If this bar is completely before the bounds of the graph, not visible.
        if (record.endTime < this.graphDataSource.startTime)
            return false;

        // If this record is completely after the current time or end time, not visible.
        if (record.startTime > this.graphDataSource.currentTime || record.startTime > this.graphDataSource.endTime)
            return false;

        return true;
    }

    filterableDataForColumn(columnIdentifier)
    {
        let value = this.data[columnIdentifier];
        if (value instanceof WI.SourceCodeLocation)
            return value.displayLocationString();

        if (value instanceof WI.CallFrame)
            return [value.functionName, value.sourceCodeLocation.displayLocationString()];

        return super.filterableDataForColumn(columnIdentifier);
    }

    didAddRecordBar(recordBar)
    {
        // Implemented by subclasses.
    }

    didRemoveRecordBar(recordBar)
    {
        // Implemented by subclasses.
    }

    didResizeColumn(columnIdentifier)
    {
        if (columnIdentifier !== "graph")
            return;

        this.needsGraphRefresh();
    }
};
