/*
 * 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;
            let treeElement = this._canvasTreeOutline.findTreeElement(canvas);
            const omitFocus = false;
            const selectedByUser = false;
            treeElement.revealAndSelect(omitFocus, selectedByUser);
            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), {multiple: true});
    }

    _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");
