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

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