/*
 * Copyright (C) 2018 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.CanvasSidebarPanel = class CanvasSidebarPanel extends WI.NavigationSidebarPanel
{
    constructor()
    {
        super("canvas", WI.UIString("Canvas"));

        this._canvas = null;
        this._recording = null;

        this._navigationBar = new WI.NavigationBar;
        this._scopeBar = null;
        this._placeholderScopeBarItem = null;

        const toolTip = WI.UIString("Start recording canvas actions.\nShift-click to record a single frame.");
        const altToolTip = WI.UIString("Stop recording canvas actions");
        this._recordButtonNavigationItem = new WI.ToggleButtonNavigationItem("record-start-stop", toolTip, altToolTip, "Images/Record.svg", "Images/Stop.svg", 13, 13);
        this._recordButtonNavigationItem.enabled = false;
        this._recordButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        this._recordButtonNavigationItem.label = WI.UIString("Start");
        this._recordButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._toggleRecording, this);
        this._navigationBar.addNavigationItem(this._recordButtonNavigationItem);

        this._navigationBar.addNavigationItem(new WI.DividerNavigationItem);

        let importButtonNavigationItem = new WI.ButtonNavigationItem("import-recording", WI.UIString("Import"), "Images/Import.svg", 15, 15);
        importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        importButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
        this._navigationBar.addNavigationItem(importButtonNavigationItem);

        this.addSubview(this._navigationBar);

        this._canvasTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
        this._canvasTreeOutline.element.classList.add("canvas");

        this._recordingNavigationBar = new WI.NavigationBar;
        this._recordingNavigationBar.element.classList.add("hidden");
        this.contentView.addSubview(this._recordingNavigationBar);

        this._recordingContentContainer = this.contentView.element.appendChild(document.createElement("div"));
        this._recordingContentContainer.className = "recording-content";

        this._recordingTreeOutline = this.contentTreeOutline;
        this._recordingContentContainer.appendChild(this._recordingTreeOutline.element);

        this._recordingTreeOutline.customIndent = true;
        this._recordingTreeOutline.registerScrollVirtualizer(this._recordingContentContainer, 20);

        this._canvasTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
        this._recordingTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);

        this._recordingProcessingOptionsContainer = null;

        this._selectedRecordingActionIndex = NaN;
    }

    // Public

    get canvas()
    {
        return this._canvas;
    }

    set canvas(canvas)
    {
        if (this._canvas === canvas)
            return;

        if (this._canvas) {
            this._canvas.removeEventListener(null, null, this);
            this._canvas.recordingCollection.removeEventListener(null, null, this);
        }

        this._canvas = canvas;
        if (this._canvas) {
            this._canvas.addEventListener(WI.Canvas.Event.RecordingStarted, this._updateRecordNavigationItem, this);
            this._canvas.addEventListener(WI.Canvas.Event.RecordingStopped, this._updateRecordNavigationItem, this);
            this._canvas.recordingCollection.addEventListener(WI.Collection.Event.ItemAdded, this._recordingAdded, this);
            this._canvas.recordingCollection.addEventListener(WI.Collection.Event.ItemRemoved, this._recordingRemoved, this);
        }

        this._canvasChanged();
        this._updateRecordNavigationItem();
        this._updateRecordingScopeBar();
    }

    set recording(recording)
    {
        if (recording === this._recording)
            return;

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

        if (recording)
            this.canvas = recording.source;

        this._recording = recording;

        if (this._recording && !this._recording.ready) {
            this._recording.addEventListener(WI.Recording.Event.ProcessedAction, this._handleRecordingProcessedAction, this);
            this._recording.addEventListener(WI.Recording.Event.StartProcessingFrame, this._handleRecordingStartProcessingFrame, this);
        }

        this._updateRecordNavigationItem();
        this._updateRecordingScopeBar();
        this._recordingChanged();
    }

    set action(action)
    {
        if (!this._recording)
            return;

        if (action === this._recording.actions[this._selectedRecordingActionIndex])
            return;

        let selectedTreeElement = this._recordingTreeOutline.selectedTreeElement;
        if (!action) {
            if (selectedTreeElement)
                selectedTreeElement.deselect();
            return;
        }

        if (selectedTreeElement && selectedTreeElement instanceof WI.FolderTreeElement) {
            let lastActionTreeElement = selectedTreeElement.children.lastValue;
            if (action === lastActionTreeElement.representedObject)
                return;
        }

        let treeElement = this._recordingTreeOutline.findTreeElement(action);
        console.assert(treeElement, "Missing tree element for recording action.", action);
        if (!treeElement)
            return;

        this._recording[WI.CanvasSidebarPanel.SelectedActionSymbol] = action;

        const omitFocus = false;
        const selectedByUser = false;
        treeElement.revealAndSelect(omitFocus, selectedByUser);

        this._selectedRecordingActionIndex = this._recording.actions.indexOf(action);
    }

    updateRepresentedObjects()
    {
        let objects = this.contentBrowser.currentRepresentedObjects;

        let canvas = objects.find((object) => object instanceof WI.Canvas);
        if (canvas) {
            this.canvas = canvas;
            return;
        }

        let shaderProgram = objects.find((object) => object instanceof WI.ShaderProgram);
        if (shaderProgram) {
            this.canvas = shaderProgram.canvas;
            let treeElement = this._canvasTreeOutline.findTreeElement(shaderProgram);
            const omitFocus = false;
            const selectedByUser = false;
            treeElement.revealAndSelect(omitFocus, selectedByUser);
            return;
        }

        let recording = objects.find((object) => object instanceof WI.Recording);
        if (recording) {
            this.canvas = recording.source;

            this.recording = recording;

            let recordingAction = objects.find((object) => object instanceof WI.RecordingAction);
            if (recordingAction !== recording[WI.CanvasSidebarPanel.SelectedActionSymbol])
                this.action = recordingAction;

            return;
        }

        this.canvas = null;
        this.recording = null;
    }

    shown()
    {
        super.shown();

        this.contentBrowser.addEventListener(WI.ContentBrowser.Event.CurrentRepresentedObjectsDidChange, this.updateRepresentedObjects, this);
        this.updateRepresentedObjects();

        if (this._recording) {
            this._recordingTreeOutline.updateVirtualizedElementsDebouncer.force();

            let action = this._recording[WI.CanvasSidebarPanel.SelectedActionSymbol];
            let treeElement = this._recordingTreeOutline.findTreeElement(action);
            if (treeElement) {
                const omitFocus = false;
                const selectedByUser = false;
                treeElement.revealAndSelect(omitFocus, selectedByUser);
            }
        }
    }

    hidden()
    {
        this.contentBrowser.removeEventListener(null, null, this);

        super.hidden();
    }

    canShowRepresentedObject(representedObject)
    {
        if (representedObject instanceof WI.CanvasCollection)
            return false;

        return super.canShowRepresentedObject(representedObject);
    }

    // Protected

    get scrollElement()
    {
        return this._recordingContentContainer;
    }

    hasCustomFilters()
    {
        return true;
    }

    matchTreeElementAgainstCustomFilters(treeElement)
    {
        // Keep recording frame tree elements.
        if (treeElement instanceof WI.FolderTreeElement)
            return true;

        // Always show the Initial State tree element.
        if (treeElement instanceof WI.RecordingActionTreeElement && treeElement.representedObject instanceof WI.RecordingInitialStateAction)
            return true;

        return super.matchTreeElementAgainstCustomFilters(treeElement);
    }

    initialLayout()
    {
        super.initialLayout();

        let filterFunction = (treeElement) => {
            if (!(treeElement.representedObject instanceof WI.RecordingAction))
                return false;

            return treeElement.representedObject.isVisual || treeElement.representedObject instanceof WI.RecordingInitialStateAction;
        };

        const activatedByDefault = false;
        const defaultToolTip = WI.UIString("Only show visual actions");
        const activatedToolTip = WI.UIString("Show all actions");
        this.filterBar.addFilterBarButton("recording-show-visual-only", filterFunction, activatedByDefault, defaultToolTip, activatedToolTip, "Images/Paint.svg", 15, 15);
    }

    // Private

    _recordingAdded(event)
    {
        this.recording = event.data.item;
    }

    _recordingRemoved(event)
    {
        this._updateRecordingScopeBar();

        let recording = event.data.item;
        if (recording === this.recording)
            this.recording = this._canvas ? Array.from(this._canvas.recordingCollection).lastValue : null;
    }

    _scopeBarSelectionChanged()
    {
        let selectedScopeBarItem = this._scopeBar.selectedItems[0];
        this.recording = selectedScopeBarItem.__recording || null;
    }

    _toggleRecording(event)
    {
        if (!this._canvas)
            return;

        if (this._canvas.recordingActive)
            this._canvas.stopRecording();
        else {
            let singleFrame = event.data.nativeEvent.shiftKey;
            this._canvas.startRecording(singleFrame);
        }
    }

    _handleImportButtonNavigationItemClicked(event)
    {
        WI.FileUtilities.importJSON((result) => WI.canvasManager.processJSON(result));
    }

    _treeSelectionDidChange(event)
    {
        let treeElement = event.target.selectedTreeElement;
        if (!treeElement)
            return;

        if ((treeElement instanceof WI.CanvasTreeElement) || (treeElement instanceof WI.ShaderProgramTreeElement)) {
            if (this._placeholderScopeBarItem)
                this._placeholderScopeBarItem.selected = true;

            this.showDefaultContentViewForTreeElement(treeElement);
            return;
        }

        if (treeElement instanceof WI.FolderTreeElement)
            treeElement = treeElement.children.lastValue;

        if (!(treeElement instanceof WI.RecordingActionTreeElement))
            return;

        console.assert(this._recording, "Missing recording for action tree element.", treeElement);
        this._recording[WI.CanvasSidebarPanel.SelectedActionSymbol] = treeElement.representedObject;

        const onlyExisting = true;
        let recordingContentView = this.contentBrowser.contentViewForRepresentedObject(this._recording, onlyExisting);
        if (!recordingContentView)
            return;

        this.contentBrowser.showContentView(recordingContentView);

        this._selectedRecordingActionIndex = treeElement.index;
        recordingContentView.updateActionIndex(this._selectedRecordingActionIndex);
    }

    _canvasChanged()
    {
        this._canvasTreeOutline.removeChildren();

        if (!this._canvas) {
            this._recordingNavigationBar.element.classList.add("hidden");
            return;
        }

        const showRecordings = false;
        let canvasTreeElement = new WI.CanvasTreeElement(this._canvas, showRecordings);
        canvasTreeElement.expanded = true;
        this._canvasTreeOutline.appendChild(canvasTreeElement);

        const omitFocus = false;
        const selectedByUser = false;
        canvasTreeElement.revealAndSelect(omitFocus, selectedByUser);

        if (WI.Canvas.ContextType.Canvas2D || this._canvas.contextType === WI.Canvas.ContextType.WebGL || this._canvas.contextType === WI.Canvas.ContextType.WebGL2)
            this._recordButtonNavigationItem.enabled = true;

        this.recording = null;
    }

    _recordingChanged()
    {
        this._recordingTreeOutline.removeChildren();

        this._selectedRecordingActionIndex = NaN;

        if (this._recordingProcessingOptionsContainer) {
            this._recordingProcessingOptionsContainer.remove();
            this._recordingProcessingOptionsContainer = null;
        }

        if (!this._recording)
            return;

        if (!this._recording.ready) {
            if (!this._recording.processing)
                this._recording.startProcessing();

            if (!this._recordingProcessingOptionsContainer) {
                this._recordingProcessingOptionsContainer = this._recordingContentContainer.appendChild(document.createElement("div"));
                this._recordingProcessingOptionsContainer.classList.add("recording-processing-options");

                let createPauseButton = () => {
                    let spinner = new WI.IndeterminateProgressSpinner;
                    this._recordingProcessingOptionsContainer.appendChild(spinner.element);

                    let pauseButton = this._recordingProcessingOptionsContainer.appendChild(document.createElement("button"));
                    pauseButton.textContent = WI.UIString("Pause Processing");
                    pauseButton.addEventListener("click", (event) => {
                        this._recording.stopProcessing();

                        spinner.element.remove();
                        pauseButton.remove();
                        createResumeButton();
                    });
                };

                let createResumeButton = () => {
                    let resumeButton = this._recordingProcessingOptionsContainer.appendChild(document.createElement("button"));
                    resumeButton.textContent = WI.UIString("Resume Processing");
                    resumeButton.addEventListener("click", (event) => {
                        this._recording.startProcessing();

                        resumeButton.remove();
                        createPauseButton();
                    });
                };

                if (this._recording.processing)
                    createPauseButton();
                else
                    createResumeButton();
            }
        }

        this.contentBrowser.showContentViewForRepresentedObject(this._recording);

        if (this._scopeBar) {
            let scopeBarItem = this._scopeBar.item(this._recording.displayName);
            console.assert(scopeBarItem, "Missing scopeBarItem for recording.", this._recording);
            scopeBarItem.selected = true;
        }

        let initialStateAction = this._recording.actions[0];
        if (initialStateAction.ready && !this._recordingTreeOutline.getCachedTreeElement(initialStateAction)) {
            this._recordingTreeOutline.appendChild(new WI.RecordingActionTreeElement(initialStateAction, 0, this._recording.type));

            if (!this._recording[WI.CanvasSidebarPanel.SelectedActionSymbol])
                this.action = initialStateAction;
        }

        let cumulativeActionIndex = 0;
        this._recording.frames.forEach((frame, frameIndex) => {
            if (!frame.actions[0].ready)
                return;

            let folder = this._recordingTreeOutline.getCachedTreeElement(frame);
            if (!folder)
                folder = this._createRecordingFrameTreeElement(frame, frameIndex, this._recordingTreeOutline);

            for (let action of frame.actions) {
                ++cumulativeActionIndex;

                if (!action.ready || this._recordingTreeOutline.getCachedTreeElement(action))
                    break;

                this._createRecordingActionTreeElement(action, cumulativeActionIndex, folder);
            }
        });
    }

    _updateRecordNavigationItem()
    {
        if (!this._canvas || !(this._canvas.contextType === WI.Canvas.ContextType.Canvas2D || this._canvas.contextType === WI.Canvas.ContextType.WebGL || this._canvas.contextType === WI.Canvas.ContextType.WebGL2)) {
            this._recordButtonNavigationItem.enabled = false;
            return;
        }

        this._recordButtonNavigationItem.toggled = this._canvas.recordingActive;
        this._recordButtonNavigationItem.label = this._recordButtonNavigationItem.toggled ? WI.UIString("Stop") : WI.UIString("Start");
    }

    _updateRecordingScopeBar()
    {
        if (this._scopeBar) {
            this._placeholderScopeBarItem = null;

            this._recordingNavigationBar.removeNavigationItem(this._scopeBar);
            this._scopeBar = null;
        }

        this._recordingNavigationBar.element.classList.toggle("hidden", !this._canvas);

        let hasRecordings = this._recording || (this._canvas && this._canvas.recordingCollection.size);
        this.element.classList.toggle("has-recordings", hasRecordings);
        if (!hasRecordings)
            return;

        let scopeBarItems = [];
        let selectedScopeBarItem = null;

        let createScopeBarItem = (recording) => {
            let scopeBarItem = new WI.ScopeBarItem(recording.displayName, recording.displayName);
            if (recording === this._recording)
                selectedScopeBarItem = scopeBarItem;
            else
                scopeBarItem.selected = false;
            scopeBarItem.__recording = recording;
            scopeBarItems.push(scopeBarItem);
        };

        if (this._canvas && this._canvas.recordingCollection) {
            for (let recording of this._canvas.recordingCollection)
                createScopeBarItem(recording);
        }

        if (this._recording && (!this._canvas || !this._canvas.recordingCollection.has(this._recording)))
            createScopeBarItem(this._recording);

        if (!selectedScopeBarItem) {
            selectedScopeBarItem = scopeBarItems[0];

            this._placeholderScopeBarItem = new WI.ScopeBarItem("canvas-recording-scope-bar-item-placeholder", WI.UIString("Recordings"), {exclusive: true, hidden: true});
            this._placeholderScopeBarItem.selected = true;

            scopeBarItems.unshift(this._placeholderScopeBarItem);
        }

        this._scopeBar = new WI.ScopeBar("canvas-recording-scope-bar", scopeBarItems, selectedScopeBarItem, true);
        this._scopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._scopeBarSelectionChanged, this);
        this._recordingNavigationBar.insertNavigationItem(this._scopeBar, 0);
    }

    _createRecordingFrameTreeElement(frame, index, parent)
    {
        let folder = new WI.FolderTreeElement(WI.UIString("Frame %d").format((index + 1).toLocaleString()), frame);

        if (!isNaN(frame.duration)) {
            const higherResolution = true;
            folder.status = Number.secondsToString(frame.duration / 1000, higherResolution);
        }

        parent.appendChild(folder);

        return folder;
    }

    _createRecordingActionTreeElement(action, index, parent)
    {
        let treeElement = new WI.RecordingActionTreeElement(action, index, this._recording.type);

        parent.appendChild(treeElement);

        if (parent instanceof WI.FolderTreeElement && parent.representedObject instanceof WI.RecordingFrame) {
            if (action !== parent.representedObject.actions.lastValue) {
                parent.addClassName("processing");

                if (!(parent.subtitle instanceof HTMLProgressElement))
                    parent.subtitle = document.createElement("progress");

                if (parent.statusElement)
                    parent.subtitle.style.setProperty("width", `calc(100% - ${parent.statusElement.offsetWidth + 4}px`);

                parent.subtitle.value = parent.representedObject.actions.indexOf(action) / parent.representedObject.actions.length;
            } else {
                parent.removeClassName("processing");
                if (parent.representedObject.incomplete)
                    parent.subtitle = WI.UIString("Incomplete");
                else
                    parent.subtitle = "";
            }
        }

        if (action === this._recording[WI.CanvasSidebarPanel.SelectedActionSymbol])
            this.action = action;

        return treeElement;
    }

    _handleRecordingProcessedAction(event)
    {
        let {action, index} = event.data;

        this._recordingTreeOutline.element.dataset.indent = Number.countDigits(index);

        let isInitialStateAction = !index;

        console.assert(isInitialStateAction || this._recordingTreeOutline.children.lastValue instanceof WI.FolderTreeElement, "There should be a WI.FolderTreeElement for the frame for this action.");
        this._createRecordingActionTreeElement(action, index, isInitialStateAction ? this._recordingTreeOutline : this._recordingTreeOutline.children.lastValue);

        if (!this._recording[WI.CanvasSidebarPanel.SelectedActionSymbol]) {
            console.assert(action === this._recording.actions[0]);
            this.action = this._recording.actions[0];
        }

        if (this._recording.ready) {
            this._recording.removeEventListener(null, null, this);

            if (this._recordingProcessingOptionsContainer) {
                this._recordingProcessingOptionsContainer.remove();
                this._recordingProcessingOptionsContainer = null;
            }
        }
    }

    _handleRecordingStartProcessingFrame(event)
    {
        let {frame, index} = event.data;

        this._createRecordingFrameTreeElement(frame, index, this._recordingTreeOutline);
    }
};

WI.CanvasSidebarPanel.SelectedActionSymbol = Symbol("selected-action");
