/*
 * 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({
            content: JSON.stringify(this.representedObject.toJSON()),
            suggestedName: filename + ".json",
            forceSaveAs: true,
        });
    }

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

        let filename = this.representedObject.displayName;

        WI.FileUtilities.save({
            content: this.representedObject.toHTML(),
            suggestedName: filename + ".html",
            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;
