/*
 * Copyright (C) 2017 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.CanvasTabContentView = class CanvasTabContentView extends WI.ContentBrowserTabContentView
{
    constructor(representedObject)
    {
        console.assert(!representedObject || representedObject instanceof WI.Canvas);

        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.CanvasTabContentView.tabInfo());

        const navigationSidebarPanelConstructor = WI.CanvasSidebarPanel;
        const detailsSidebarPanelConstructors = [WI.RecordingStateDetailsSidebarPanel, WI.RecordingTraceDetailsSidebarPanel, WI.CanvasDetailsSidebarPanel];
        const disableBackForward = true;
        super("canvas", ["canvas"], tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward);

        this._canvasCollection = new WI.CanvasCollection;

        this._canvasTreeOutline = new WI.TreeOutline;
        this._canvasTreeOutline.allowsRepeatSelection = true;
        this._canvasTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._canvasTreeOutlineSelectionDidChange, this);

        this._overviewTreeElement = new WI.GeneralTreeElement("canvas-overview", WI.UIString("Overview"), null, this._canvasCollection);
        this._canvasTreeOutline.appendChild(this._overviewTreeElement);

        this._savedRecordingsTreeElement = new WI.FolderTreeElement(WI.UIString("Saved Recordings"), WI.RecordingCollection);
        this._savedRecordingsTreeElement.hidden = true;
        this._overviewTreeElement.appendChild(this._savedRecordingsTreeElement);

        this._recordShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Space, this._handleSpace.bind(this));
        this._recordShortcut.implicitlyPreventsDefault = false;
        this._recordShortcut.disabled = true;

        this._recordSingleFrameShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Shift, WI.KeyboardShortcut.Key.Space, this._handleSpace.bind(this));
        this._recordSingleFrameShortcut.implicitlyPreventsDefault = false;
        this._recordSingleFrameShortcut.disabled = true;

        WI.canvasManager.enable();
    }

    static tabInfo()
    {
        return {
            image: "Images/Canvas.svg",
            title: WI.UIString("Canvas"),
        };
    }

    static isTabAllowed()
    {
        return !!window.CanvasAgent;
    }

    // Public

    treeElementForRepresentedObject(representedObject)
    {
        return this._canvasTreeOutline.findTreeElement(representedObject);
    }

    get type()
    {
        return WI.CanvasTabContentView.Type;
    }

    get supportsSplitContentBrowser()
    {
        return true;
    }

    get managesNavigationSidebarPanel()
    {
        return true;
    }

    canShowRepresentedObject(representedObject)
    {
        return representedObject instanceof WI.Canvas
            || representedObject instanceof WI.CanvasCollection
            || representedObject instanceof WI.Recording
            || representedObject instanceof WI.ShaderProgram;
    }

    shown()
    {
        super.shown();

        this._recordShortcut.disabled = false;
        this._recordSingleFrameShortcut.disabled = false;

        if (!this.contentBrowser.currentContentView)
            this.showRepresentedObject(this._canvasCollection);
    }

    hidden()
    {
        this._recordShortcut.disabled = true;
        this._recordSingleFrameShortcut.disabled = true;

        super.hidden();
    }

    closed()
    {
        WI.canvasManager.disable();

        super.closed();
    }

    restoreStateFromCookie(cookie)
    {
        // FIXME: implement once <https://webkit.org/b/177606> is complete.
    }

    saveStateToCookie(cookie)
    {
        // FIXME: implement once <https://webkit.org/b/177606> is complete.
    }

    async handleFileDrop(files)
    {
        await WI.FileUtilities.readJSON(files, (result) => WI.canvasManager.processJSON(result));
    }

    // Protected

    attached()
    {
        super.attached();

        WI.canvasManager.addEventListener(WI.CanvasManager.Event.CanvasAdded, this._handleCanvasAdded, this);
        WI.canvasManager.addEventListener(WI.CanvasManager.Event.CanvasRemoved, this._handleCanvasRemoved, this);
        WI.canvasManager.addEventListener(WI.CanvasManager.Event.RecordingSaved, this._handleRecordingSavedOrStopped, this);
        WI.Canvas.addEventListener(WI.Canvas.Event.RecordingStopped, this._handleRecordingSavedOrStopped, this);

        let canvases = WI.canvasManager.canvases;

        for (let canvas of this._canvasCollection) {
            if (!canvases.includes(canvas))
                this._removeCanvas(canvas);
        }

        for (let canvas of canvases) {
            if (!this._canvasCollection.has(canvas))
                this._addCanvas(canvas);
        }

        this._savedRecordingsTreeElement.removeChildren();
        for (let recording of WI.canvasManager.savedRecordings)
            this._addRecording(recording, {suppressShowRecording: true});
    }

    detached()
    {
        WI.Canvas.removeEventListener(null, null, this);
        WI.canvasManager.removeEventListener(null, null, this);

        super.detached();
    }

    // Private

    _addCanvas(canvas)
    {
        this._overviewTreeElement.appendChild(new WI.CanvasTreeElement(canvas));
        this._canvasCollection.add(canvas);

        const options = {
            suppressShowRecording: true,
        };

        for (let recording of canvas.recordingCollection)
            this._addRecording(recording, options);
    }

    _removeCanvas(canvas)
    {
        let treeElement = this._canvasTreeOutline.findTreeElement(canvas);
        console.assert(treeElement, "Missing tree element for canvas.", canvas);

        const suppressNotification = true;
        treeElement.deselect(suppressNotification);
        this._overviewTreeElement.removeChild(treeElement);

        this._canvasCollection.remove(canvas);

        let currentContentView = this.contentBrowser.currentContentView;
        if (currentContentView instanceof WI.CanvasContentView)
            WI.showRepresentedObject(this._canvasCollection);
        else if (currentContentView instanceof WI.RecordingContentView && canvas.recordingCollection.has(currentContentView.representedObject))
            this.contentBrowser.updateHierarchicalPathForCurrentContentView();

        let navigationSidebarPanel = this.navigationSidebarPanel;
        if (navigationSidebarPanel instanceof WI.CanvasSidebarPanel && navigationSidebarPanel.visible)
            navigationSidebarPanel.updateRepresentedObjects();

        this.showDetailsSidebarPanels();
    }

    _addRecording(recording, options = {})
    {
        if (!recording.source) {
            const subtitle = null;
            let recordingTreeElement = new WI.GeneralTreeElement(["recording"], recording.displayName, subtitle, recording);
            this._savedRecordingsTreeElement.hidden = false;
            this._savedRecordingsTreeElement.appendChild(recordingTreeElement);
        }

        if (!options.suppressShowRecording)
            this.showRepresentedObject(recording);
    }

    _handleCanvasAdded(event)
    {
        this._addCanvas(event.data.canvas);
    }

    _handleCanvasRemoved(event)
    {
        this._removeCanvas(event.data.canvas);
    }

    _canvasTreeOutlineSelectionDidChange(event)
    {
        let selectedElement = this._canvasTreeOutline.selectedTreeElement;
        if (!selectedElement)
            return;

        let representedObject = selectedElement.representedObject;
        if (!this.canShowRepresentedObject(representedObject)) {
            console.assert(false, "Unexpected representedObject.", representedObject);
            return;
        }

        this.showRepresentedObject(representedObject);
    }

    _handleRecordingSavedOrStopped(event)
    {
        let {recording, initiatedByUser, imported} = event.data;
        if (!recording)
            return;

        let options = {};

        // Always show imported recordings.
        if (recording.source || !imported)
            options.suppressShowRecording = !initiatedByUser || this.contentBrowser.currentRepresentedObjects.some((representedObject) => representedObject instanceof WI.Recording);

        this._addRecording(recording, options);
    }

    _handleSpace(event)
    {
        if (WI.isEventTargetAnEditableField(event))
            return;

        if (!this.navigationSidebarPanel)
            return;

        let canvas = this.navigationSidebarPanel.canvas;
        if (!canvas)
            return;

        if (canvas.recordingActive)
            canvas.stopRecording();
        else {
            let singleFrame = !!event.shiftKey;
            canvas.startRecording(singleFrame);
        }

        event.preventDefault();
    }
};

WI.CanvasTabContentView.Type = "canvas";
