/*
 * Copyright (C) 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.RenderingFrameTimelineView = class RenderingFrameTimelineView extends WI.TimelineView
{
    constructor(timeline, extraArguments)
    {
        super(timeline, extraArguments);

        console.assert(WI.TimelineRecord.Type.RenderingFrame);

        var scopeBarItems = [];
        for (var key in WI.RenderingFrameTimelineView.DurationFilter) {
            var value = WI.RenderingFrameTimelineView.DurationFilter[key];
            scopeBarItems.push(new WI.ScopeBarItem(value, WI.RenderingFrameTimelineView.displayNameForDurationFilter(value)));
        }

        this._scopeBar = new WI.ScopeBar("rendering-frame-scope-bar", scopeBarItems, scopeBarItems[0], true);
        this._scopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._scopeBarSelectionDidChange, this);

        let columns = {name: {}, totalTime: {}, scriptTime: {}, layoutTime: {}, paintTime: {}, otherTime: {}, startTime: {}, location: {}};

        columns.name.title = WI.UIString("Name");
        columns.name.width = "20%";
        columns.name.icon = true;
        columns.name.disclosure = true;
        columns.name.locked = true;

        columns.totalTime.title = WI.UIString("Total Time");
        columns.totalTime.width = "15%";
        columns.totalTime.aligned = "right";

        columns.scriptTime.title = WI.RenderingFrameTimelineRecord.displayNameForTaskType(WI.RenderingFrameTimelineRecord.TaskType.Script);
        columns.scriptTime.width = "10%";
        columns.scriptTime.aligned = "right";

        columns.layoutTime.title = WI.RenderingFrameTimelineRecord.displayNameForTaskType(WI.RenderingFrameTimelineRecord.TaskType.Layout);
        columns.layoutTime.width = "10%";
        columns.layoutTime.aligned = "right";

        columns.paintTime.title = WI.RenderingFrameTimelineRecord.displayNameForTaskType(WI.RenderingFrameTimelineRecord.TaskType.Paint);
        columns.paintTime.width = "10%";
        columns.paintTime.aligned = "right";

        columns.otherTime.title = WI.RenderingFrameTimelineRecord.displayNameForTaskType(WI.RenderingFrameTimelineRecord.TaskType.Other);
        columns.otherTime.width = "10%";
        columns.otherTime.aligned = "right";

        columns.startTime.title = WI.UIString("Start Time");
        columns.startTime.width = "15%";
        columns.startTime.aligned = "right";

        columns.location.title = WI.UIString("Location");

        for (var column in columns)
            columns[column].sortable = true;

        this._dataGrid = new WI.TimelineDataGrid(columns);
        this._dataGrid.sortColumnIdentifier = "startTime";
        this._dataGrid.sortOrder = WI.DataGrid.SortOrder.Ascending;
        this._dataGrid.createSettings("rendering-frame-timeline-view");

        this.setupDataGrid(this._dataGrid);

        this.element.classList.add("rendering-frame");
        this.addSubview(this._dataGrid);

        timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._renderingFrameTimelineRecordAdded, this);

        this._pendingRecords = [];

        for (let record of timeline.records)
            this._processRecord(record);
    }

    static displayNameForDurationFilter(filter)
    {
        switch (filter) {
            case WI.RenderingFrameTimelineView.DurationFilter.All:
                return WI.UIString("All");
            case WI.RenderingFrameTimelineView.DurationFilter.OverOneMillisecond:
                return WI.UIString("Over 1 ms");
            case WI.RenderingFrameTimelineView.DurationFilter.OverFifteenMilliseconds:
                return WI.UIString("Over 15 ms");
            default:
                console.error("Unknown filter type", filter);
        }

        return null;
    }

    // Public

    get showsLiveRecordingData() { return false; }

    shown()
    {
        super.shown();

        this._dataGrid.shown();
    }

    hidden()
    {
        this._dataGrid.hidden();

        super.hidden();
    }

    closed()
    {
        console.assert(this.representedObject instanceof WI.Timeline);
        this.representedObject.removeEventListener(null, null, this);

        this._dataGrid.closed();
    }

    get selectionPathComponents()
    {
        let dataGridNode = this._dataGrid.selectedNode;
        if (!dataGridNode || dataGridNode.hidden)
            return null;

        let pathComponents = [];

        while (dataGridNode && !dataGridNode.root) {
            console.assert(dataGridNode instanceof WI.TimelineDataGridNode);
            if (dataGridNode.hidden)
                return null;

            let pathComponent = new WI.TimelineDataGridNodePathComponent(dataGridNode);
            pathComponent.addEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this.dataGridNodePathComponentSelected, this);
            pathComponents.unshift(pathComponent);
            dataGridNode = dataGridNode.parent;
        }

        return pathComponents;
    }

    get filterStartTime()
    {
        let records = this.representedObject.records;
        let startIndex = this.startTime;
        if (startIndex >= records.length)
            return Infinity;

        return records[startIndex].startTime;
    }

    get filterEndTime()
    {
        let records = this.representedObject.records;
        let endIndex = this.endTime - 1;
        if (endIndex >= records.length)
            return Infinity;

        return records[endIndex].endTime;
    }

    reset()
    {
        super.reset();

        this._dataGrid.reset();

        this._pendingRecords = [];
    }

    // Protected

    dataGridNodePathComponentSelected(event)
    {
        let dataGridNode = event.data.pathComponent.timelineDataGridNode;
        console.assert(dataGridNode.dataGrid === this._dataGrid);

        dataGridNode.revealAndSelect();
    }

    matchDataGridNodeAgainstCustomFilters(node)
    {
        if (!super.matchDataGridNodeAgainstCustomFilters(node))
            return false;

        console.assert(node instanceof WI.TimelineDataGridNode);
        console.assert(this._scopeBar.selectedItems.length === 1);
        let selectedScopeBarItem = this._scopeBar.selectedItems[0];
        if (!selectedScopeBarItem || selectedScopeBarItem.id === WI.RenderingFrameTimelineView.DurationFilter.All)
            return true;

        while (node && !(node.record instanceof WI.RenderingFrameTimelineRecord))
            node = node.parent;

        console.assert(node, "Cannot apply duration filter: no RenderingFrameTimelineRecord found.");
        if (!node)
            return false;

        let minimumDuration = selectedScopeBarItem.id === WI.RenderingFrameTimelineView.DurationFilter.OverOneMillisecond ? 0.001 : 0.015;
        return node.record.duration > minimumDuration;
    }

    layout()
    {
        this._processPendingRecords();
    }

    // Private

    _processPendingRecords()
    {
        if (!this._pendingRecords.length)
            return;

        for (let renderingFrameTimelineRecord of this._pendingRecords) {
            console.assert(renderingFrameTimelineRecord instanceof WI.RenderingFrameTimelineRecord);

            let dataGridNode = new WI.RenderingFrameTimelineDataGridNode(renderingFrameTimelineRecord, {
                graphDataSource: this,
            });
            this._dataGrid.addRowInSortOrder(dataGridNode);

            let stack = [{children: renderingFrameTimelineRecord.children, parentDataGridNode: dataGridNode, index: 0}];
            while (stack.length) {
                let entry = stack.lastValue;
                if (entry.index >= entry.children.length) {
                    stack.pop();
                    continue;
                }

                let childRecord = entry.children[entry.index];
                let childDataGridNode = null;
                if (childRecord.type === WI.TimelineRecord.Type.Layout) {
                    childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, {
                        graphDataSource: this,
                    });

                    this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode);
                } else if (childRecord.type === WI.TimelineRecord.Type.Script) {
                    let rootNodes = [];
                    if (childRecord.profile) {
                        // FIXME: Support using the bottom-up tree once it is implemented.
                        rootNodes = childRecord.profile.topDownRootNodes;
                    }

                    childDataGridNode = new WI.ScriptTimelineDataGridNode(childRecord, {
                        graphDataSource: this,
                    });

                    this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode);

                    for (let profileNode of rootNodes) {
                        let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, {
                            graphDataSource: this,
                        });
                        this._dataGrid.addRowInSortOrder(profileNodeDataGridNode, childDataGridNode);
                    }
                }

                if (childDataGridNode && childRecord.children.length)
                    stack.push({children: childRecord.children, parentDataGridNode: childDataGridNode, index: 0});
                ++entry.index;
            }
        }

        this._pendingRecords = [];
    }

    _renderingFrameTimelineRecordAdded(event)
    {
        let renderingFrameTimelineRecord = event.data.record;
        console.assert(renderingFrameTimelineRecord instanceof WI.RenderingFrameTimelineRecord);
        console.assert(renderingFrameTimelineRecord.children.length, "Missing child records for rendering frame.");

        this._processRecord(renderingFrameTimelineRecord);

        this.needsLayout();
    }

    _processRecord(renderingFrameTimelineRecord)
    {
        this._pendingRecords.push(renderingFrameTimelineRecord);
    }

    _scopeBarSelectionDidChange()
    {
        this._dataGrid.filterDidChange();
    }
};

WI.RenderingFrameTimelineView.DurationFilter = {
    All: "rendering-frame-timeline-view-duration-filter-all",
    OverOneMillisecond: "rendering-frame-timeline-view-duration-filter-over-1-ms",
    OverFifteenMilliseconds: "rendering-frame-timeline-view-duration-filter-over-15-ms"
};

