/*
 * 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.RecordingContentView = class RecordingContentView extends WI.ContentView
{
    constructor(representedObject)
    {
        console.assert(representedObject instanceof WI.Recording);

        super(representedObject);

        let isCanvas2D = this.representedObject.type === WI.Recording.Type.Canvas2D;
        let isCanvasBitmapRenderer = this.representedObject.type === WI.Recording.Type.CanvasBitmapRenderer;
        let isCanvasWebGL = this.representedObject.type === WI.Recording.Type.CanvasWebGL;
        let isCanvasWebGL2 = this.representedObject.type === WI.Recording.Type.CanvasWebGL2;

        this._index = NaN;
        this._action = null;
        this._snapshots = [];
        this._initialContent = null;
        this._generateContentThrottler = new Throttler(() => {
            if (isCanvas2D)
                this._generateContentCanvas2D(this._index);
            else if (isCanvasBitmapRenderer || isCanvasWebGL || isCanvasWebGL2)
                this._generateContentFromSnapshot(this._index);
        }, 200);

        this.element.classList.add("recording", this.representedObject.type);

        if (isCanvas2D || isCanvasBitmapRenderer || isCanvasWebGL || isCanvasWebGL2) {
            if (isCanvas2D && WI.ImageUtilities.supportsCanvasPathDebugging()) {
                this._pathContext = null;

                this._showPathButtonNavigationItem = new WI.ActivateButtonNavigationItem("show-path", WI.UIString("Show Path"), WI.UIString("Hide Path"), "Images/Path.svg", 16, 16);
                this._showPathButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._showPathButtonClicked, this);
                this._showPathButtonNavigationItem.activated = !!WI.settings.showCanvasPath.value;
            }

            this._showGridButtonNavigationItem = new WI.ActivateButtonNavigationItem("show-grid", WI.UIString("Show transparency grid"), WI.UIString("Hide transparency grid"), "Images/NavigationItemCheckers.svg", 13, 13);
            this._showGridButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
            this._showGridButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._showGridButtonClicked, this);
            this._showGridButtonNavigationItem.activated = !!WI.settings.showImageGrid.value;

            this._exportButtonNavigationItem = new WI.ButtonNavigationItem("export-recording", WI.UIString("Export"), "Images/Export.svg", 15, 15);
            this._exportButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
            this._exportButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
            this._exportButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleExportNavigationItemClicked, this);
            this._updateExportButton();
        }
    }

    // Public

    get navigationItems()
    {
        let isCanvas2D = this.representedObject.type === WI.Recording.Type.Canvas2D;
        let isCanvasBitmapRenderer = this.representedObject.type === WI.Recording.Type.CanvasBitmapRenderer;
        let isCanvasWebGL = this.representedObject.type === WI.Recording.Type.CanvasWebGL;
        let isCanvasWebGL2 = this.representedObject.type === WI.Recording.Type.CanvasWebGL2;
        if (!isCanvas2D && !isCanvasBitmapRenderer && !isCanvasWebGL && !isCanvasWebGL2)
            return [];

        let navigationItems = [this._exportButtonNavigationItem, new WI.DividerNavigationItem];
        if (isCanvas2D && WI.ImageUtilities.supportsCanvasPathDebugging())
            navigationItems.push(this._showPathButtonNavigationItem);

        navigationItems.push(this._showGridButtonNavigationItem);
        return navigationItems;
    }

    get supplementalRepresentedObjects()
    {
        return this._action ? [this._action] : [];
    }

    updateActionIndex(index)
    {
        if (!this.representedObject)
            return;

        if (this._index === index)
            return;

        console.assert(index >= 0 && index < this.representedObject.actions.length);
        if (index < 0 || index >= this.representedObject.actions.length)
            return;

        this._index = index;

        this._updateSliderValue();

        if (this.didInitialLayout)
            this._generateContentThrottler.fire();

        this._action = this.representedObject.actions[this._index];

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

    shown()
    {
        super.shown();

        let isCanvas2D = this.representedObject.type === WI.Recording.Type.Canvas2D;
        let isCanvasBitmapRenderer = this.representedObject.type === WI.Recording.Type.CanvasBitmapRenderer;
        let isCanvasWebGL = this.representedObject.type === WI.Recording.Type.CanvasWebGL;
        let isCanvasWebGL2 = this.representedObject.type === WI.Recording.Type.CanvasWebGL2;
        if (isCanvas2D || isCanvasBitmapRenderer || isCanvasWebGL || isCanvasWebGL2) {
            if (isCanvas2D)
                this._updateCanvasPath();
            this._updateImageGrid();
        }
    }

    hidden()
    {
        super.hidden();

        this._generateContentThrottler.cancel();
    }

    // Protected

    get supportsSave()
    {
        return true;
    }

    get saveData()
    {
        return {customSaveHandler: () => { this._exportRecording(); }};
    }

    initialLayout()
    {
        let previewHeader = this.element.appendChild(document.createElement("header"));

        let sliderContainer = previewHeader.appendChild(document.createElement("div"));
        sliderContainer.className = "slider-container";

        this._previewContainer = this.element.appendChild(document.createElement("div"));
        this._previewContainer.className = "preview-container";

        this._sliderValueElement = sliderContainer.appendChild(document.createElement("div"));
        this._sliderValueElement.className = "slider-value";

        this._sliderElement = sliderContainer.appendChild(document.createElement("input"));
        this._sliderElement.addEventListener("input", this._sliderChanged.bind(this));
        this._sliderElement.type = "range";
        this._sliderElement.min = 0;
        this._sliderElement.max = 0;

        if (!this.representedObject.ready) {
            this.representedObject.addEventListener(WI.Recording.Event.ProcessedAction, this._handleRecordingProcessedAction, this);

            if (!this.representedObject.processing)
                this.representedObject.startProcessing();
        }

        this._updateSliderValue();

        if (!isNaN(this._index))
            this._generateContentThrottler.fire();
    }

    // Private

    _exportRecording()
    {
        let filename = this.representedObject.displayName;

        WI.FileUtilities.save({
            url: WI.FileUtilities.inspectorURLForFilename(filename + ".json"),
            content: JSON.stringify(this.representedObject.toJSON()),
            forceSaveAs: true,
        });
    }

    _exportReduction()
    {
        if (!this.representedObject.ready) {
            InspectorFrontendHost.beep();
            return;
        }

        let filename = this.representedObject.displayName;

        WI.FileUtilities.save({
            url: WI.FileUtilities.inspectorURLForFilename(filename + ".html"),
            content: this.representedObject.toHTML(),
            forceSaveAs: true,
        });
    }

    _generateContentCanvas2D(index)
    {
        let imageLoad = (event) => {
            // Loading took too long and the current action index has already changed.
            if (index !== this._index)
                return;

            this._generateContentCanvas2D(index);
        };

        let initialState = this.representedObject.initialState;
        if (initialState.content && !this._initialContent) {
            this._initialContent = new Image;
            this._initialContent.src = initialState.content;
            this._initialContent.addEventListener("load", imageLoad);
            return;
        }

        let snapshotIndex = Math.floor(index / WI.RecordingContentView.SnapshotInterval);
        let snapshot = this._snapshots[snapshotIndex];

        let showCanvasPath = WI.ImageUtilities.supportsCanvasPathDebugging() && WI.settings.showCanvasPath.value;
        let indexOfLastBeginPathAction = Infinity;

        let actions = this.representedObject.actions;

        let applyActions = (from, to, callback) => {
            let saveCount = 0;
            snapshot.context.save();

            for (let attribute in snapshot.attributes)
                snapshot.element[attribute] = snapshot.attributes[attribute];

            if (snapshot.content) {
                snapshot.context.clearRect(0, 0, snapshot.element.width, snapshot.element.height);
                snapshot.context.drawImage(snapshot.content, 0, 0);
            }

            for (let state of snapshot.states) {
                state.apply(this.representedObject.type, snapshot.context);

                ++saveCount;
                snapshot.context.save();
            }

            let lastPathPoint = {};
            let subPathStartPoint = {};

            for (let i = from; i <= to; ++i) {
                if (actions[i].name === "save")
                    ++saveCount;
                else if (actions[i].name === "restore") {
                    if (!saveCount) // Only attempt to restore if save has been called.
                        continue;
                }

                actions[i].apply(snapshot.context);
            }

            if (showCanvasPath && indexOfLastBeginPathAction <= to) {
                if (!this._pathContext) {
                    let pathCanvas = document.createElement("canvas");
                    pathCanvas.classList.add("path");
                    this._pathContext = pathCanvas.getContext("2d");
                }

                this._pathContext.canvas.width = snapshot.element.width;
                this._pathContext.canvas.height = snapshot.element.height;
                this._pathContext.clearRect(0, 0, snapshot.element.width, snapshot.element.height);

                this._pathContext.save();

                this._pathContext.fillStyle = "hsla(0, 0%, 100%, 0.75)";
                this._pathContext.fillRect(0, 0, snapshot.element.width, snapshot.element.height);

                function actionModifiesPath(action) {
                    switch (action.name) {
                    case "arc":
                    case "arcTo":
                    case "beginPath":
                    case "bezierCurveTo":
                    case "closePath":
                    case "ellipse":
                    case "lineTo":
                    case "moveTo":
                    case "quadraticCurveTo":
                    case "rect":
                        return true;
                    }

                    return false;
                }

                for (let i = indexOfLastBeginPathAction; i <= to; ++i) {
                    if (!actionModifiesPath(actions[i]))
                        continue;

                    lastPathPoint = {x: this._pathContext.currentX, y: this._pathContext.currentY};

                    if (i === indexOfLastBeginPathAction)
                        this._pathContext.setTransform(snapshot.context.getTransform());

                    let isMoveTo = actions[i].name === "moveTo";
                    this._pathContext.lineWidth = isMoveTo ? 0.5 : 1;
                    this._pathContext.setLineDash(isMoveTo ? [5, 5] : []);
                    this._pathContext.strokeStyle = i === to ? "red" : "black";

                    this._pathContext.beginPath();
                    if (!isEmptyObject(lastPathPoint))
                        this._pathContext.moveTo(lastPathPoint.x, lastPathPoint.y);

                    if (actions[i].name === "closePath" && !isEmptyObject(subPathStartPoint)) {
                        this._pathContext.lineTo(subPathStartPoint.x, subPathStartPoint.y);
                        subPathStartPoint = {};
                    } else {
                        actions[i].apply(this._pathContext, {nameOverride: isMoveTo ? "lineTo" : null});
                        if (isMoveTo)
                            subPathStartPoint = {x: this._pathContext.currentX, y: this._pathContext.currentY};
                    }

                    this._pathContext.stroke();
                }

                this._pathContext.restore();
                this._previewContainer.appendChild(this._pathContext.canvas);
            } else if (this._pathContext)
                this._pathContext.canvas.remove();

            snapshot.context.restore();
            while (saveCount-- > 0)
                snapshot.context.restore();
        };

        if (!snapshot) {
            snapshot = this._snapshots[snapshotIndex] = {};
            snapshot.index = snapshotIndex * WI.RecordingContentView.SnapshotInterval;
            while (snapshot.index && actions[snapshot.index].name !== "beginPath")
                --snapshot.index;

            snapshot.context = this.representedObject.createContext();
            snapshot.element = snapshot.context.canvas;

            let lastSnapshotIndex = snapshotIndex;
            while (--lastSnapshotIndex >= 0) {
                if (this._snapshots[lastSnapshotIndex])
                    break;
            }

            let startIndex = 0;
            if (lastSnapshotIndex < 0) {
                snapshot.content = this._initialContent;
                snapshot.states = actions[0].states;
                snapshot.attributes = Object.shallowCopy(initialState.attributes);
            } else {
                let lastSnapshot = this._snapshots[lastSnapshotIndex];
                snapshot.content = lastSnapshot.content;
                snapshot.states = lastSnapshot.states;
                snapshot.attributes = {};
                for (let attribute in initialState.attributes)
                    snapshot.attributes[attribute] = lastSnapshot.element[attribute];

                startIndex = lastSnapshot.index;
            }

            applyActions(startIndex, snapshot.index - 1);
            if (snapshot.index > 0)
                snapshot.states = actions[snapshot.index - 1].states;

            snapshot.content = new Image;
            snapshot.content.src = snapshot.element.toDataURL();
            snapshot.content.addEventListener("load", imageLoad);
            return;
        }

        this._previewContainer.removeChildren();

        if (showCanvasPath) {
            indexOfLastBeginPathAction = this._index;
            while (indexOfLastBeginPathAction > snapshot.index && actions[indexOfLastBeginPathAction].name !== "beginPath")
                --indexOfLastBeginPathAction;
        }

        applyActions(snapshot.index, this._index);

        this._previewContainer.insertAdjacentElement("afterbegin", snapshot.element);
        this._updateImageGrid();
    }

    _generateContentFromSnapshot(index)
    {
        let imageLoad = (event) => {
            // Loading took too long and the current action index has already changed.
            if (index !== this._index)
                return;

            this._generateContentFromSnapshot(index);
        };

        let initialState = this.representedObject.initialState;
        if (initialState.content && !this._initialContent) {
            this._initialContent = new Image;
            this._initialContent.src = initialState.content;
            this._initialContent.addEventListener("load", imageLoad);
            return;
        }

        let actions = this.representedObject.actions;

        let visualIndex = index;
        while (!actions[visualIndex].isVisual && !(actions[visualIndex] instanceof WI.RecordingInitialStateAction))
            visualIndex--;

        let snapshot = this._snapshots[visualIndex];
        if (!snapshot) {
            if (actions[visualIndex].snapshot) {
                snapshot = this._snapshots[visualIndex] = {element: new Image};
                snapshot.element.src = actions[visualIndex].snapshot;
                snapshot.element.addEventListener("load", imageLoad);
                return;
            }

            if (actions[visualIndex] instanceof WI.RecordingInitialStateAction)
                snapshot = this._snapshots[visualIndex] = {element: this._initialContent};
        }

        if (snapshot) {
            this._previewContainer.removeChildren();
            this._previewContainer.appendChild(snapshot.element);

            this._updateImageGrid();
        }
    }

    _updateExportButton()
    {
        if (this.representedObject.type === WI.Recording.Type.Canvas2D && this.representedObject.ready)
            this._exportButtonNavigationItem.tooltip = WI.UIString("Export recording (%s)\nShift-click to export a HTML reduction").format(WI.saveKeyboardShortcut.displayName);
        else
            this._exportButtonNavigationItem.tooltip = WI.UIString("Export recording (%s)").format(WI.saveKeyboardShortcut.displayName);
    }

    _updateCanvasPath()
    {
        let activated = WI.settings.showCanvasPath.value;

        if (this._showPathButtonNavigationItem.activated !== activated)
            this._generateContentCanvas2D(this._index);

        this._showPathButtonNavigationItem.activated = activated;
    }

    _updateImageGrid()
    {
        let activated = WI.settings.showImageGrid.value;
        this._showGridButtonNavigationItem.activated = activated;

        if (this.didInitialLayout && !isNaN(this._index))
            this._previewContainer.firstElementChild.classList.toggle("show-grid", activated);
    }

    _updateSliderValue()
    {
        if (!this._sliderElement)
            return;

        let visualActionIndexes = this.representedObject.visualActionIndexes;
        let visualActionIndex = 0;
        if (this._index > 0) {
            while (visualActionIndex < visualActionIndexes.length && visualActionIndexes[visualActionIndex] <= this._index)
                visualActionIndex++;
        }

        this._sliderElement.value = visualActionIndex;
        this._sliderElement.max = visualActionIndexes.length;
        this._sliderValueElement.textContent = WI.UIString("%d of %d").format(visualActionIndex, visualActionIndexes.length);
    }

    _showPathButtonClicked(event)
    {
        WI.settings.showCanvasPath.value = !this._showPathButtonNavigationItem.activated;

        this._updateCanvasPath();
    }

    _showGridButtonClicked(event)
    {
        WI.settings.showImageGrid.value = !this._showGridButtonNavigationItem.activated;

        this._updateImageGrid();
    }

    _handleExportNavigationItemClicked(event)
    {
        if (event.data.nativeEvent.shiftKey && this.representedObject.type === WI.Recording.Type.Canvas2D && this.representedObject.ready)
            this._exportReduction();
        else
            this._exportRecording();
    }

    _sliderChanged()
    {
        let index = 0;

        let visualActionIndex = parseInt(this._sliderElement.value) - 1;
        if (visualActionIndex !== -1)
            index = this.representedObject.visualActionIndexes[visualActionIndex];

        this.updateActionIndex(index);
    }

    _handleRecordingProcessedAction(event)
    {
        this._updateExportButton();

        this._updateSliderValue();

        if (this.representedObject.ready)
            this.representedObject.removeEventListener(null, null, this);
    }
};

WI.RecordingContentView.SnapshotInterval = 5000;
