/*
 * Copyright (C) 2013, 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.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView
{
    constructor(recording, extraArguments)
    {
        console.assert(recording instanceof WI.TimelineRecording);

        super(recording, extraArguments);

        this._recording = recording;
        this._pendingRepresentedObjects = [];
        this._resourceDataGridNodeMap = new Map;

        if (WI.TimelineRecording.sourceCodeTimelinesSupported() && !this._recording.imported) {
            WI.settings.timelineOverviewGroupBySourceCode.addEventListener(WI.Setting.Event.Changed, this._handleGroupBySourceCodeSettingChanged, this);

            this._groupBySourceCodeNavigationItem = new WI.CheckboxNavigationItem("overview-timeline-group-by-resource", WI.UIString("Group By Resource"), WI.settings.timelineOverviewGroupBySourceCode.value);
            this._groupBySourceCodeNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleGroupBySourceCodeNavigationItemCheckedDidChange, this);
        }

        let columns = {name: {}, source: {}, graph: {}};

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

        columns.source.title = WI.UIString("Source");
        columns.source.width = "10%";
        columns.source.icon = true;
        columns.source.locked = true;
        if (this._shouldGroupBySourceCode)
            columns.source.hidden = true;

        this._timelineRuler = new WI.TimelineRuler;
        this._timelineRuler.allowsClippedLabels = true;

        columns.graph.width = "70%";
        columns.graph.headerView = this._timelineRuler;
        columns.graph.locked = true;

        this._dataGrid = new WI.TimelineDataGrid(columns);

        this.setupDataGrid(this._dataGrid);

        this._currentTimeMarker = new WI.TimelineMarker(0, WI.TimelineMarker.Type.CurrentTime);
        this._timelineRuler.addMarker(this._currentTimeMarker);

        this.element.classList.add("overview");
        this.addSubview(this._dataGrid);

        for (let timeline of this._relevantTimelines)
            timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._handleTimelineRecordAdded, this);

        recording.addEventListener(WI.TimelineRecording.Event.SourceCodeTimelineAdded, this._sourceCodeTimelineAdded, this);
        recording.addEventListener(WI.TimelineRecording.Event.MarkerAdded, this._markerAdded, this);
        recording.addEventListener(WI.TimelineRecording.Event.Reset, this._recordingReset, this);

        this._loadExistingRecords();
    }

    // Public

    get secondsPerPixel()
    {
        return this._timelineRuler.secondsPerPixel;
    }

    set secondsPerPixel(x)
    {
        this._timelineRuler.secondsPerPixel = x;
    }

    shown()
    {
        super.shown();

        this._timelineRuler.updateLayout(WI.View.LayoutReason.Resize);
    }

    closed()
    {
        for (let timeline of this._recording.timelines.values())
            timeline.removeEventListener(null, null, this);

        this._recording.removeEventListener(null, null, this);
    }

    get navigationItems()
    {
        let navigationItems = [];
        if (this._groupBySourceCodeNavigationItem)
            navigationItems.push(this._groupBySourceCodeNavigationItem);
        return navigationItems;
    }

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

    reset()
    {
        super.reset();

        this._dataGrid.reset();

        this._pendingRepresentedObjects = [];
        this._resourceDataGridNodeMap.clear();
    }

    // Protected

    get showsImportedRecordingMessage()
    {
        return true;
    }

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

        dataGridNode.revealAndSelect();
    }

    layout()
    {
        let oldZeroTime = this._timelineRuler.zeroTime;
        let oldStartTime = this._timelineRuler.startTime;
        let oldEndTime = this._timelineRuler.endTime;
        let oldCurrentTime = this._currentTimeMarker.time;

        this._timelineRuler.zeroTime = this.zeroTime;
        this._timelineRuler.startTime = this.startTime;
        this._timelineRuler.endTime = this.endTime;
        this._currentTimeMarker.time = this.currentTime;

        // The TimelineDataGridNode graphs are positioned with percentages, so they auto resize with the view.
        // We only need to refresh the graphs when the any of the times change.
        if (this.zeroTime !== oldZeroTime || this.startTime !== oldStartTime || this.endTime !== oldEndTime || this.currentTime !== oldCurrentTime) {
            let dataGridNode = this._dataGrid.children[0];
            while (dataGridNode) {
                dataGridNode.refreshGraph();
                dataGridNode = dataGridNode.traverseNextNode(true, null, true);
            }
        }

        this._processPendingRepresentedObjects();
    }

    // Private

    get _relevantTimelines()
    {
        let timelines = [];
        for (let [type, timeline] of this._recording.timelines) {
            if (type === WI.TimelineRecord.Type.RenderingFrame || type === WI.TimelineRecord.Type.CPU || type === WI.TimelineRecord.Type.Memory)
                continue;

            timelines.push(timeline);
        }
        return timelines;
    }

    get _shouldGroupBySourceCode()
    {
        // Always show imported records as non-grouped.
        if (this._recording.imported)
            return false;

        return WI.TimelineRecording.sourceCodeTimelinesSupported() && WI.settings.timelineOverviewGroupBySourceCode.value;
    }

    _loadExistingRecords()
    {
        this._pendingRepresentedObjects = [];
        this._resourceDataGridNodeMap.clear();

        this._dataGrid.removeChildren();

        if (this._shouldGroupBySourceCode) {
            let networkTimeline = this._recording.timelines.get(WI.TimelineRecord.Type.Network);
            if (networkTimeline)
                this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(networkTimeline.records.map((record) => record.resource));

            this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(this._recording.sourceCodeTimelines);
        } else {
            for (let timeline of this._relevantTimelines)
                this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(timeline.records);
        }

        this.needsLayout();
    }

    _compareDataGridNodesByStartTime(a, b)
    {
        function getStartTime(dataGridNode)
        {
            if (dataGridNode instanceof WI.ResourceTimelineDataGridNode)
                return dataGridNode.resource.firstTimestamp;
            if (dataGridNode instanceof WI.SourceCodeTimelineTimelineDataGridNode)
                return dataGridNode.sourceCodeTimeline.startTime;

            console.error("Unknown data grid node.", dataGridNode);
            return 0;
        }

        let result = getStartTime(a) - getStartTime(b);
        if (result)
            return result;

        // Fallback to comparing titles.
        return a.displayName().extendedLocaleCompare(b.displayName());
    }

    _insertDataGridNode(dataGridNode, parentDataGridNode)
    {
        console.assert(dataGridNode);
        console.assert(!dataGridNode.parent);

        if (!parentDataGridNode)
            parentDataGridNode = this._dataGrid;

        parentDataGridNode.insertChild(dataGridNode, insertionIndexForObjectInListSortedByFunction(dataGridNode, parentDataGridNode.children, this._compareDataGridNodesByStartTime));
    }

    _addResourceToDataGridIfNeeded(resource)
    {
        console.assert(resource);
        if (!resource)
            return null;

        // FIXME: replace with this._dataGrid.findDataGridNode(resource) once <https://webkit.org/b/155305> is fixed.
        let dataGridNode = this._resourceDataGridNodeMap.get(resource);
        if (!dataGridNode) {
            let resourceTimelineRecord = this._networkTimeline ? this._networkTimeline.recordForResource(resource) : null;
            if (!resourceTimelineRecord)
                resourceTimelineRecord = new WI.ResourceTimelineRecord(resource);

            dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, {
                graphDataSource: this,
                includesGraph: true,
            });
            this._resourceDataGridNodeMap.set(resource, dataGridNode);
        }

        if (!dataGridNode.parent) {
            let parentFrame = resource.parentFrame;
            if (!parentFrame)
                return null;

            let expandedByDefault = false;
            if (parentFrame.mainResource === resource || parentFrame.provisionalMainResource === resource) {
                parentFrame = parentFrame.parentFrame;
                expandedByDefault = !parentFrame; // Main frame expands by default.
            }

            if (expandedByDefault)
                dataGridNode.expand();

            let parentDataGridNode = null;
            if (parentFrame) {
                // Find the parent main resource, adding it if needed, to append this resource as a child.
                let parentResource = parentFrame.provisionalMainResource || parentFrame.mainResource;

                parentDataGridNode = this._addResourceToDataGridIfNeeded(parentResource);
                console.assert(parentDataGridNode);
                if (!parentDataGridNode)
                    return null;
            }

            this._insertDataGridNode(dataGridNode, parentDataGridNode);
        }

        dataGridNode.refresh();
        return dataGridNode;
    }

    _addSourceCodeTimeline(sourceCodeTimeline)
    {
        let dataGridNode = this._resourceDataGridNodeMap.get(sourceCodeTimeline);
        if (!dataGridNode) {
            dataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, {
                graphDataSource: this,
            });
            this._resourceDataGridNodeMap.set(sourceCodeTimeline, dataGridNode);
        }

        if (!dataGridNode.parent) {
            let parentDataGridNode = sourceCodeTimeline.sourceCodeLocation ? this._addResourceToDataGridIfNeeded(sourceCodeTimeline.sourceCode) : null;
            this._insertDataGridNode(dataGridNode, parentDataGridNode);
        }
    }

    _processPendingRepresentedObjects()
    {
        if (!this._pendingRepresentedObjects.length)
            return;

        for (var representedObject of this._pendingRepresentedObjects) {
            if (this._shouldGroupBySourceCode) {
                if (representedObject instanceof WI.Resource)
                    this._addResourceToDataGridIfNeeded(representedObject);
                else if (representedObject instanceof WI.SourceCodeTimeline)
                    this._addSourceCodeTimeline(representedObject);
                else
                    console.error("Unknown represented object", representedObject);
            } else {
                const options = {
                    graphDataSource: this,
                    shouldShowPopover: true,
                };

                let dataGridNode = null;
                if (representedObject instanceof WI.ResourceTimelineRecord)
                    dataGridNode = new WI.ResourceTimelineDataGridNode(representedObject, options);
                else if (representedObject instanceof WI.LayoutTimelineRecord)
                    dataGridNode = new WI.LayoutTimelineDataGridNode(representedObject, options);
                else if (representedObject instanceof WI.MediaTimelineRecord)
                    dataGridNode = new WI.MediaTimelineDataGridNode(representedObject, options);
                else if (representedObject instanceof WI.ScriptTimelineRecord)
                    dataGridNode = new WI.ScriptTimelineDataGridNode(representedObject, options);
                else if (representedObject instanceof WI.HeapAllocationsTimelineRecord)
                    dataGridNode = new WI.HeapAllocationsTimelineDataGridNode(representedObject, options);

                console.assert(dataGridNode, representedObject);
                if (!dataGridNode)
                    continue;

                let comparator = (a, b) => {
                    return a.record.startTime - b.record.startTime;
                };

                this._dataGrid.insertChild(dataGridNode, insertionIndexForObjectInListSortedByFunction(dataGridNode, this._dataGrid.children, comparator));
            }
        }

        this._pendingRepresentedObjects = [];
    }

    _handleGroupBySourceCodeSettingChanged(event)
    {
        let groupBySourceCode = this._shouldGroupBySourceCode;
        this._dataGrid.disclosureColumnIdentifier = groupBySourceCode ? "name" : undefined;
        this._dataGrid.setColumnVisible("source", !groupBySourceCode);
        if (this._groupBySourceCodeNavigationItem)
            this._groupBySourceCodeNavigationItem.checked = groupBySourceCode;

        this._loadExistingRecords();
    }

    _handleGroupBySourceCodeNavigationItemCheckedDidChange(event)
    {
        WI.settings.timelineOverviewGroupBySourceCode.value = !WI.settings.timelineOverviewGroupBySourceCode.value;
    }

    _handleTimelineRecordAdded(event)
    {
        let {record} = event.data;

        if (this._shouldGroupBySourceCode) {
            if (event.target.type !== WI.TimelineRecord.Type.Network)
                return;

            console.assert(record instanceof WI.ResourceTimelineRecord);

            this._pendingRepresentedObjects.push(record.resource);
        } else
            this._pendingRepresentedObjects.push(record);

        this.needsLayout();
    }

    _sourceCodeTimelineAdded(event)
    {
        if (!this._shouldGroupBySourceCode)
            return;

        var sourceCodeTimeline = event.data.sourceCodeTimeline;
        console.assert(sourceCodeTimeline);
        if (!sourceCodeTimeline)
            return;

        this._pendingRepresentedObjects.push(sourceCodeTimeline);

        this.needsLayout();
    }

    _markerAdded(event)
    {
        this._timelineRuler.addMarker(event.data.marker);
    }

    _recordingReset(event)
    {
        this._timelineRuler.clearMarkers();
        this._timelineRuler.addMarker(this._currentTimeMarker);
    }
};
