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

        console.assert(timeline.type === WI.TimelineRecord.Type.HeapAllocations, timeline);

        this.element.classList.add("heap-allocations");

        let columns = {
            name: {
                title: WI.UIString("Name"),
                width: "150px",
                icon: true,
            },
            timestamp: {
                title: WI.UIString("Time"),
                width: "80px",
                sortable: true,
                aligned: "right",
            },
            size: {
                title: WI.UIString("Size"),
                width: "80px",
                sortable: true,
                aligned: "right",
            },
            liveSize: {
                title: WI.UIString("Live Size"),
                width: "80px",
                sortable: true,
                aligned: "right",
            },
        };

        this._importButtonNavigationItem = new WI.ButtonNavigationItem("import", WI.UIString("Import"), "Images/Import.svg", 15, 15);
        this._importButtonNavigationItem.tooltip = WI.UIString("Import");
        this._importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        this._importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._importButtonNavigationItemClicked, this);

        let snapshotTooltip = WI.UIString("Take snapshot");
        this._takeHeapSnapshotButtonItem = new WI.ButtonNavigationItem("take-snapshot", snapshotTooltip, "Images/Camera.svg", 16, 16);
        this._takeHeapSnapshotButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._takeHeapSnapshotClicked, this);

        let defaultToolTip = WI.UIString("Compare snapshots");
        let activatedToolTip = WI.UIString("Cancel comparison");
        this._compareHeapSnapshotsButtonItem = new WI.ActivateButtonNavigationItem("compare-heap-snapshots", defaultToolTip, activatedToolTip, "Images/Compare.svg", 16, 16);
        this._compareHeapSnapshotsButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._compareHeapSnapshotsClicked, this);
        this._compareHeapSnapshotsButtonItem.enabled = false;
        this._compareHeapSnapshotsButtonItem.activated = false;

        this._compareHeapSnapshotHelpTextItem = new WI.TextNavigationItem("compare-heap-snapshot-help-text", "");

        this._selectingComparisonHeapSnapshots = false;
        this._baselineDataGridNode = null;
        this._baselineHeapSnapshotTimelineRecord = null;
        this._heapSnapshotDiff = null;

        this._snapshotListScrollTop = 0;
        this._showingSnapshotList = true;

        this._snapshotListPathComponent = new WI.HierarchicalPathComponent(WI.UIString("Snapshot List"), "snapshot-list-icon", "snapshot-list", false, false);
        this._snapshotListPathComponent.addEventListener(WI.HierarchicalPathComponent.Event.Clicked, this._snapshotListPathComponentClicked, this);

        this._unseenRecords = [];
        this._unseenRecordsBannerView = new WI.BannerView(WI.UIString("There are new snapshots that have been filtered", "There are new snapshots that have been filtered @ Heap Allocations Timeline View", "Message displayed in a banner when one or more snapshots that the user has not yet seen are being filtered."), {
            actionButtonMessage: WI.UIString("Clear Filters", "Clear Filters @ Heap Allocations Timeline View", "Text for button that will clear both text filters and time range filters."),
            showDismissButton: true,
        });
        this._unseenRecordsBannerView.addEventListener(WI.BannerView.Event.ActionButtonClicked, this._handleUnseenRecordsBannerClearFiltersClicked, this);
        this._unseenRecordsBannerView.addEventListener(WI.BannerView.Event.DismissButtonClicked, this._handleUnseenRecordsBannerDismissClicked, this);

        this._dataGrid = new WI.TimelineDataGrid(columns);
        this._dataGrid.sortColumnIdentifier = "timestamp";
        this._dataGrid.sortOrder = WI.DataGrid.SortOrder.Ascending;
        this._dataGrid.createSettings("heap-allocations-timeline-view");
        this._dataGrid.addEventListener(WI.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
        this.setupDataGrid(this._dataGrid);
        this.addSubview(this._dataGrid);

        this._contentViewContainer = new WI.ContentViewContainer;
        this._contentViewContainer.addEventListener(WI.ContentViewContainer.Event.CurrentContentViewDidChange, this._currentContentViewDidChange, this);
        WI.ContentView.addEventListener(WI.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this);

        this._pendingRecords = Array.from(timeline.records);

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

        WI.HeapSnapshotProxy.addEventListener(WI.HeapSnapshotProxy.Event.Invalidated, this._heapSnapshotInvalidated, this);
        WI.HeapSnapshotWorkerProxy.singleton().addEventListener(WI.HeapSnapshotWorkerProxy.Event.Collection, this._heapSnapshotCollectionEvent, this);
    }

    // Public

    get scrollableElements()
    {
        if (this._showingSnapshotList)
            return [this._dataGrid.scrollContainer];
        if (this._contentViewContainer.currentContentView)
            return this._contentViewContainer.currentContentView.scrollableElements;
        return [];
    }

    showHeapSnapshotList()
    {
        if (this._showingSnapshotList)
            return;

        this._showingSnapshotList = true;
        this._heapSnapshotDiff = null;
        this._cancelSelectComparisonHeapSnapshots();

        this.removeSubview(this._contentViewContainer);
        this.addSubview(this._dataGrid);

        this._dataGrid.scrollContainer.scrollTop = this._snapshotListScrollTop;

        this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
        this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
    }

    showHeapSnapshotTimelineRecord(heapSnapshotTimelineRecord)
    {
        if (this._showingSnapshotList) {
            this._snapshotListScrollTop = this._dataGrid.scrollContainer.scrollTop;
            this.removeSubview(this._dataGrid);
            this.addSubview(this._contentViewContainer);
        }

        this._showingSnapshotList = false;
        this._heapSnapshotDiff = null;
        this._cancelSelectComparisonHeapSnapshots();

        for (let dataGridNode of this._dataGrid.children) {
            if (dataGridNode.record === heapSnapshotTimelineRecord) {
                dataGridNode.hidden = false;
                dataGridNode.select();
                break;
            }
        }

        let shouldTriggerContentViewUpdate = this._contentViewContainer.currentContentView && this._contentViewContainer.currentContentView.representedObject === heapSnapshotTimelineRecord.heapSnapshot;

        this._contentViewContainer.showContentViewForRepresentedObject(heapSnapshotTimelineRecord.heapSnapshot);

        if (shouldTriggerContentViewUpdate)
            this._currentContentViewDidChange();
    }

    showHeapSnapshotDiff(heapSnapshotDiff)
    {
        if (this._showingSnapshotList) {
            this.removeSubview(this._dataGrid);
            this.addSubview(this._contentViewContainer);
        }

        this._showingSnapshotList = false;
        this._heapSnapshotDiff = heapSnapshotDiff;

        this._contentViewContainer.showContentViewForRepresentedObject(heapSnapshotDiff);
    }

    // Protected

    get navigationItems()
    {
        if (this._showingSnapshotList) {
            let items = [this._importButtonNavigationItem, this._takeHeapSnapshotButtonItem, this._compareHeapSnapshotsButtonItem];
            if (this._selectingComparisonHeapSnapshots)
                items.push(this._compareHeapSnapshotHelpTextItem);
            return items;
        }

        if (this._contentViewContainer.currentContentView)
            return this._contentViewContainer.currentContentView.navigationItems;

        return [];
    }

    get selectionPathComponents()
    {
        let components = [this._snapshotListPathComponent];

        if (this._showingSnapshotList)
            return components;

        if (this._heapSnapshotDiff) {
            let firstSnapshotIdentifier = this._heapSnapshotDiff.snapshot1.identifier;
            let secondSnapshotIdentifier = this._heapSnapshotDiff.snapshot2.identifier;
            let diffComponent = new WI.HierarchicalPathComponent(WI.UIString("Snapshot Comparison (%d and %d)").format(firstSnapshotIdentifier, secondSnapshotIdentifier), "snapshot-diff-icon", "snapshot-diff");
            components.push(diffComponent);
        } else if (this._dataGrid.selectedNode) {
            let heapSnapshotPathComponent = new WI.HeapAllocationsTimelineDataGridNodePathComponent(this._dataGrid.selectedNode);
            heapSnapshotPathComponent.addEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._snapshotPathComponentSelected, this);
            components.push(heapSnapshotPathComponent);
        }

        if (this._contentViewContainer.currentContentView)
            components.pushAll(this._contentViewContainer.currentContentView.selectionPathComponents);

        return components;
    }

    selectRecord(record)
    {
        if (record)
            this.showHeapSnapshotTimelineRecord(record);
        else
            this.showHeapSnapshotList();
    }

    closed()
    {
        this.representedObject.removeEventListener(WI.Timeline.Event.RecordAdded, this._heapAllocationsTimelineRecordAdded, this);

        this._dataGrid.closed();

        this._contentViewContainer.closeAllContentViews();

        WI.ContentView.removeEventListener(WI.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this);
        WI.HeapSnapshotProxy.removeEventListener(WI.HeapSnapshotProxy.Event.Invalidated, this._heapSnapshotInvalidated, this);
        WI.HeapSnapshotWorkerProxy.singleton().removeEventListener(WI.HeapSnapshotWorkerProxy.Event.Collection, this._heapSnapshotCollectionEvent, this);
    }

    layout()
    {
        super.layout();

        if (!this._pendingRecords.length)
            return;

        for (let heapAllocationsTimelineRecord of this._pendingRecords) {
            let dataGridNode = new WI.HeapAllocationsTimelineDataGridNode(heapAllocationsTimelineRecord, {
                graphDataSource: this,
                heapAllocationsView: this,
            });
            this._dataGrid.addRowInSortOrder(dataGridNode);
            if (dataGridNode.hidden)
                this._unseenRecords.push(dataGridNode);
        }

        this._pendingRecords = [];
        this._updateUnseenRecordsBannerView();
        this._updateCompareHeapSnapshotButton();
    }

    reset()
    {
        super.reset();

        this._dataGrid.reset();

        this.showHeapSnapshotList();
        this._pendingRecords = [];
        this._unseenRecords = [];
        this._updateUnseenRecordsBannerView();
        this._updateCompareHeapSnapshotButton();
    }

    updateFilter(filters)
    {
        if (this._showingSnapshotList) {
            this._dataGrid.filterText = filters ? filters.text : "";
            return;
        }

        console.assert(this._contentViewContainer.currentContentView);
        this._contentViewContainer.currentContentView.updateFilter(filters);
    }

    filterDidChange()
    {
        super.filterDidChange();

        this._updateUnseenRecordsBannerView();
    }

    // Private

    _heapAllocationsTimelineRecordAdded(event)
    {
        this._pendingRecords.push(event.data.record);

        this.needsLayout();
    }

    _heapSnapshotCollectionEvent(event)
    {
        function updateHeapSnapshotForEvent(heapSnapshot) {
            if (heapSnapshot.invalid)
                return;
            heapSnapshot.updateForCollectionEvent(event);
        }

        for (let node of this._dataGrid.children)
            updateHeapSnapshotForEvent(node.record.heapSnapshot);
        for (let record of this._pendingRecords)
            updateHeapSnapshotForEvent(record.heapSnapshot);
        if (this._heapSnapshotDiff)
            updateHeapSnapshotForEvent(this._heapSnapshotDiff);
    }

    _snapshotListPathComponentClicked(event)
    {
        this.showHeapSnapshotList();
    }

    _snapshotPathComponentSelected(event)
    {
        console.assert(event.data.pathComponent.representedObject instanceof WI.HeapAllocationsTimelineRecord);
        this.showHeapSnapshotTimelineRecord(event.data.pathComponent.representedObject);
    }

    _currentContentViewDidChange(event)
    {
        this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
        this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
    }

    _contentViewSelectionPathComponentDidChange(event)
    {
        if (event.target !== this._contentViewContainer.currentContentView)
            return;
        this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
    }

    _heapSnapshotInvalidated(event)
    {
        let heapSnapshot = event.target;

        if (this._baselineHeapSnapshotTimelineRecord) {
            if (heapSnapshot === this._baselineHeapSnapshotTimelineRecord.heapSnapshot)
                this._cancelSelectComparisonHeapSnapshots();
        }

        if (this._heapSnapshotDiff) {
            if (heapSnapshot === this._heapSnapshotDiff.snapshot1 || heapSnapshot === this._heapSnapshotDiff.snapshot2)
                this.showHeapSnapshotList();
        } else if (this._dataGrid.selectedNode) {
            if (heapSnapshot === this._dataGrid.selectedNode.record.heapSnapshot)
                this.showHeapSnapshotList();
        }

        this._updateCompareHeapSnapshotButton();
    }

    _updateCompareHeapSnapshotButton()
    {
        let hasAtLeastTwoValidSnapshots = false;

        let count = 0;
        for (let node of this._dataGrid.children) {
            if (node.revealed && !node.hidden && !node.record.heapSnapshot.invalid) {
                count++;
                if (count === 2) {
                    hasAtLeastTwoValidSnapshots = true;
                    break;
                }
            }
        }

        this._compareHeapSnapshotsButtonItem.enabled = hasAtLeastTwoValidSnapshots;
    }

    _updateUnseenRecordsBannerView()
    {
        this._unseenRecords = this._unseenRecords.filter((record) => record.hidden);
        if (this._unseenRecords.length) {
            if (this._unseenRecordsBannerView.parentView !== this)
                this.insertSubviewBefore(this._unseenRecordsBannerView, this._dataGrid);
        } else {
            if (this._unseenRecordsBannerView.parentView === this)
                this.removeSubview(this._unseenRecordsBannerView);
        }
    }

    _importButtonNavigationItemClicked()
    {
        WI.FileUtilities.importText((result) => {
            let snapshotStringData = result.text;
            let workerProxy = WI.HeapSnapshotWorkerProxy.singleton();
            workerProxy.createImportedSnapshot(snapshotStringData, result.filename, ({objectId, snapshot: serializedSnapshot}) => {
                let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
                snapshot.snapshotStringData = snapshotStringData;
                const timestamp = NaN;
                WI.timelineManager.heapSnapshotAdded(timestamp, snapshot);
                this.dispatchEventToListeners(WI.TimelineView.Event.NeedsEntireSelectedRange);
            });
        }, {multiple: true});
    }

    _takeHeapSnapshotClicked()
    {
        WI.heapManager.snapshot((error, timestamp, snapshotStringData) => {
            let workerProxy = WI.HeapSnapshotWorkerProxy.singleton();
            workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
                let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
                snapshot.snapshotStringData = snapshotStringData;
                WI.timelineManager.heapSnapshotAdded(timestamp, snapshot);
                this.dispatchEventToListeners(WI.TimelineView.Event.NeedsEntireSelectedRange);
            });
        });
    }

    _cancelSelectComparisonHeapSnapshots()
    {
        if (!this._selectingComparisonHeapSnapshots)
            return;

        if (this._baselineDataGridNode)
            this._baselineDataGridNode.clearBaseline();

        this._selectingComparisonHeapSnapshots = false;
        this._baselineDataGridNode = null;
        this._baselineHeapSnapshotTimelineRecord = null;

        this._compareHeapSnapshotsButtonItem.activated = false;

        this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
    }

    _compareHeapSnapshotsClicked(event)
    {
        let newActivated = !this._compareHeapSnapshotsButtonItem.activated;
        this._compareHeapSnapshotsButtonItem.activated = newActivated;

        if (!newActivated) {
            this._cancelSelectComparisonHeapSnapshots();
            return;
        }

        if (this._dataGrid.selectedNode)
            this._dataGrid.selectedNode.deselect();

        this._selectingComparisonHeapSnapshots = true;
        this._baselineHeapSnapshotTimelineRecord = null;
        this._compareHeapSnapshotHelpTextItem.text = WI.UIString("Select baseline snapshot");

        this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
    }

    _dataGridNodeSelected(event)
    {
        if (!this._selectingComparisonHeapSnapshots)
            return;

        let dataGridNode = this._dataGrid.selectedNode;
        if (!dataGridNode)
            return;

        let heapAllocationsTimelineRecord = dataGridNode.record;

        // Cancel the selection if the heap snapshot is invalid, or was already selected as the baseline.
        if (heapAllocationsTimelineRecord.heapSnapshot.invalid || this._baselineHeapSnapshotTimelineRecord === heapAllocationsTimelineRecord) {
            this._dataGrid.selectedNode.deselect();
            return;
        }

        // Selected Baseline.
        if (!this._baselineHeapSnapshotTimelineRecord) {
            this._baselineDataGridNode = dataGridNode;
            this._baselineDataGridNode.markAsBaseline();
            this._baselineHeapSnapshotTimelineRecord = heapAllocationsTimelineRecord;
            this._dataGrid.selectedNode.deselect();
            this._compareHeapSnapshotHelpTextItem.text = WI.UIString("Select comparison snapshot");
            this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
            return;
        }

        // Selected Comparison.
        let snapshot1 = this._baselineHeapSnapshotTimelineRecord.heapSnapshot;
        let snapshot2 = heapAllocationsTimelineRecord.heapSnapshot;
        if (snapshot1.identifier > snapshot2.identifier)
            [snapshot1, snapshot2] = [snapshot2, snapshot1];

        let workerProxy = WI.HeapSnapshotWorkerProxy.singleton();
        workerProxy.createSnapshotDiff(snapshot1.proxyObjectId, snapshot2.proxyObjectId, ({objectId, snapshotDiff: serializedSnapshotDiff}) => {
            let diff = WI.HeapSnapshotDiffProxy.deserialize(objectId, serializedSnapshotDiff);
            this.showHeapSnapshotDiff(diff);
        });

        this._baselineDataGridNode.clearBaseline();
        this._baselineDataGridNode = null;
        this._selectingComparisonHeapSnapshots = false;
        this._compareHeapSnapshotsButtonItem.activated = false;
    }

    _handleUnseenRecordsBannerClearFiltersClicked(event)
    {
        this.dispatchEventToListeners(WI.TimelineView.Event.NeedsFiltersCleared);
        this.dispatchEventToListeners(WI.TimelineView.Event.NeedsEntireSelectedRange);
    }

    _handleUnseenRecordsBannerDismissClicked(event)
    {
        this._unseenRecords = [];
        this._updateUnseenRecordsBannerView();
    }
};
