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

        let contentPlaceholder = WI.createMessageTextView(WI.UIString("No Canvas Contexts"));
        let descriptionElement = contentPlaceholder.appendChild(document.createElement("div"));
        descriptionElement.className = "description";
        descriptionElement.textContent = WI.UIString("Waiting for canvas contexts created by script or CSS.");

        let importNavigationItem = new WI.ButtonNavigationItem("import-recording", WI.UIString("Import"), "Images/Import.svg", 15, 15);
        importNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;

        let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to load a recording from file."), importNavigationItem);
        contentPlaceholder.appendChild(importHelpElement);

        super(representedObject, WI.CanvasContentView, contentPlaceholder);

        this.element.classList.add("canvas-overview");

        if (WI.CanvasManager.supportsRecordingAutoCapture()) {
            this._recordingAutoCaptureFrameCountInputElement = document.createElement("input");
            this._recordingAutoCaptureFrameCountInputElement.type = "number";
            this._recordingAutoCaptureFrameCountInputElement.min = 0;
            this._recordingAutoCaptureFrameCountInputElement.style.setProperty("--recording-auto-capture-input-margin", CanvasOverviewContentView.recordingAutoCaptureInputMargin + "px");
            this._recordingAutoCaptureFrameCountInputElement.addEventListener("input", this._handleRecordingAutoCaptureInput.bind(this));
            this._recordingAutoCaptureFrameCountInputElementValue = WI.settings.canvasRecordingAutoCaptureFrameCount.value;

            const label = null;
            this._recordingAutoCaptureNavigationItem = new WI.CheckboxNavigationItem("canvas-recording-auto-capture", label, !!WI.settings.canvasRecordingAutoCaptureEnabled.value);
            this._recordingAutoCaptureNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
            this._recordingAutoCaptureNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleRecordingAutoCaptureCheckedDidChange, this);

            let frameCount = this._updateRecordingAutoCaptureInputElementSize();
            this._setRecordingAutoCaptureFrameCount(frameCount);
            this._updateRecordingAutoCaptureCheckboxLabel(frameCount);
        }

        this._importButtonNavigationItem = new WI.ButtonNavigationItem("import-recording", WI.UIString("Import"), "Images/Import.svg", 15, 15);
        this._importButtonNavigationItem.tooltip = WI.UIString("Import");
        this._importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;

        this._refreshButtonNavigationItem = new WI.ButtonNavigationItem("refresh-all", WI.UIString("Refresh all"), "Images/ReloadFull.svg", 13, 13);
        this._refreshButtonNavigationItem.enabled = false;
        this._refreshButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._refreshPreviews, this);

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

        importNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
        this._importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);

        this._savedRecordingsContentView = null;
        this._savedRecordingsTreeOutline = null;
    }

    // Static

    static get recordingAutoCaptureInputMargin() { return 4; }

    // Public

    get navigationItems()
    {
        let navigationItems = [this._importButtonNavigationItem, new WI.DividerNavigationItem, this._refreshButtonNavigationItem, this._showGridButtonNavigationItem];
        if (WI.CanvasManager.supportsRecordingAutoCapture())
            navigationItems.unshift(this._recordingAutoCaptureNavigationItem, new WI.DividerNavigationItem);
        return navigationItems;
    }

    hidden()
    {
        WI.domManager.hideDOMNodeHighlight();

        super.hidden();
    }

    // Protected

    contentViewAdded(contentView)
    {
        contentView.element.addEventListener("mouseenter", this._contentViewMouseEnter);
        contentView.element.addEventListener("mouseleave", this._contentViewMouseLeave);

        if (this._savedRecordingsContentView) {
            // Ensure that the imported recordings are always last.
            this.removeSubview(this._savedRecordingsContentView);
            this.addSubview(this._savedRecordingsContentView);
        }

        this._updateNavigationItems();
    }

    contentViewRemoved(contentView)
    {
        contentView.element.removeEventListener("mouseenter", this._contentViewMouseEnter);
        contentView.element.removeEventListener("mouseleave", this._contentViewMouseLeave);

        this._updateNavigationItems();
    }

    attached()
    {
        super.attached();

        WI.settings.showImageGrid.addEventListener(WI.Setting.Event.Changed, this._updateShowImageGrid, this);
        WI.settings.canvasRecordingAutoCaptureEnabled.addEventListener(WI.Setting.Event.Changed, this._handleCanvasRecordingAutoCaptureEnabledChanged, this);
        WI.settings.canvasRecordingAutoCaptureFrameCount.addEventListener(WI.Setting.Event.Changed, this._handleCanvasRecordingAutoCaptureFrameCountChanged, this);

        WI.canvasManager.addEventListener(WI.CanvasManager.Event.RecordingSaved, this._handleRecordingSaved, this);

        if (this._savedRecordingsTreeOutline)
            this._savedRecordingsTreeOutline.removeChildren();
        for (let recording of WI.canvasManager.savedRecordings)
            this._addSavedRecording(recording);
    }

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

        WI.settings.canvasRecordingAutoCaptureFrameCount.removeEventListener(null, null, this);
        WI.settings.canvasRecordingAutoCaptureEnabled.removeEventListener(null, null, this);
        WI.settings.showImageGrid.removeEventListener(null, null, this);

        super.detached();
    }

    // Private

    get _itemMargin()
    {
        return parseInt(window.getComputedStyle(this.element).getPropertyValue("--item-margin"));
    }

    _refreshPreviews()
    {
        for (let canvasContentView of this.subviews)
            canvasContentView.refreshPreview();
    }

    _updateNavigationItems()
    {
        let hasItems = !!this.representedObject.size;
        this._refreshButtonNavigationItem.enabled = hasItems;
        this._showGridButtonNavigationItem.enabled = hasItems;
    }

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

    _updateShowImageGrid()
    {
        this._showGridButtonNavigationItem.activated = !!WI.settings.showImageGrid.value;
    }

    _contentViewMouseEnter(event)
    {
        let contentView = WI.View.fromElement(event.target);
        if (!(contentView instanceof WI.CanvasContentView))
            return;

        let canvas = contentView.representedObject;
        if (canvas.cssCanvasName || canvas.contextType === WI.Canvas.ContextType.WebGPU) {
            canvas.requestClientNodes((clientNodes) => {
                WI.domManager.highlightDOMNodeList(clientNodes.map((node) => node.id));
            });
            return;
        }

        canvas.requestNode().then((node) => {
            if (!node || !node.ownerDocument)
                return;
            WI.domManager.highlightDOMNode(node.id);
        });
    }

    _contentViewMouseLeave(event)
    {
        WI.domManager.hideDOMNodeHighlight();
    }

    _setRecordingAutoCaptureFrameCount(frameCount)
    {
        console.assert(!isNaN(frameCount) && frameCount >= 0);

        if (this._recordingAutoCaptureNavigationItem.checked)
            frameCount = Math.max(1, frameCount);

        let enabled = frameCount > 0 && !!this._recordingAutoCaptureNavigationItem.checked;

        WI.canvasManager.setRecordingAutoCaptureFrameCount(enabled, frameCount);
    }

    _updateRecordingAutoCaptureCheckboxLabel(frameCount)
    {
        let active = document.activeElement === this._recordingAutoCaptureFrameCountInputElement;
        let selectionStart = this._recordingAutoCaptureFrameCountInputElement.selectionStart;
        let selectionEnd = this._recordingAutoCaptureFrameCountInputElement.selectionEnd;
        let direction = this._recordingAutoCaptureFrameCountInputElement.direction;

        let label = frameCount === 1 ? WI.UIString("Record first %s frame") : WI.UIString("Record first %s frames");
        let fragment = document.createDocumentFragment();
        String.format(label, [this._recordingAutoCaptureFrameCountInputElement], String.standardFormatters, fragment, (a, b) => {
            a.append(b);
            return a;
        });
        this._recordingAutoCaptureNavigationItem.label = fragment;

        if (active) {
            this._recordingAutoCaptureFrameCountInputElement.selectionStart = selectionStart;
            this._recordingAutoCaptureFrameCountInputElement.selectionEnd = selectionEnd;
            this._recordingAutoCaptureFrameCountInputElement.direction = direction;
        }
    }

    get _recordingAutoCaptureFrameCountInputElementValue()
    {
        return parseInt(this._recordingAutoCaptureFrameCountInputElement.value);
    }

    set _recordingAutoCaptureFrameCountInputElementValue(frameCount)
    {
        if (this._recordingAutoCaptureFrameCountInputElement.value || frameCount)
            this._recordingAutoCaptureFrameCountInputElement.value = frameCount;

        this._recordingAutoCaptureFrameCountInputElement.placeholder = frameCount;
    }

    _updateRecordingAutoCaptureInputElementSize()
    {
        let frameCount = this._recordingAutoCaptureFrameCountInputElementValue;
        if (isNaN(frameCount) || frameCount < 0) {
            frameCount = 0;
            this._recordingAutoCaptureFrameCountInputElementValue = frameCount;
        }

        WI.ImageUtilities.scratchCanvasContext2D((context) => {
            if (!this._recordingAutoCaptureFrameCountInputElement.__cachedFont) {
                let computedStyle = window.getComputedStyle(this._recordingAutoCaptureFrameCountInputElement);
                this._recordingAutoCaptureFrameCountInputElement.__cachedFont = computedStyle.font;
            }

            context.font = this._recordingAutoCaptureFrameCountInputElement.__cachedFont;
            let textMetrics = context.measureText(this._recordingAutoCaptureFrameCountInputElement.value || this._recordingAutoCaptureFrameCountInputElement.placeholder);
            this._recordingAutoCaptureFrameCountInputElement.style.setProperty("width", (textMetrics.width + (2 * CanvasOverviewContentView.recordingAutoCaptureInputMargin)) + "px");
        });

        return frameCount;
    }

    _addSavedRecording(recording)
    {
        console.assert(!recording.source);

        if (!this._savedRecordingsContentView) {
            this._savedRecordingsContentView = new WI.ContentView;
            this._savedRecordingsContentView.element.classList.add("canvas", "saved-recordings");
            this.addSubview(this._savedRecordingsContentView);

            let header = this._savedRecordingsContentView.element.appendChild(document.createElement("header"));
            header.textContent = WI.UIString("Saved Recordings");

            this.hideContentPlaceholder();
        }

        if (!this._savedRecordingsTreeOutline) {
            const selectable = false;
            this._savedRecordingsTreeOutline = new WI.TreeOutline(selectable);
            this._savedRecordingsTreeOutline.addEventListener(WI.TreeOutline.Event.ElementClicked, this._handleSavedRecordingClicked, this);
            this._savedRecordingsContentView.element.appendChild(this._savedRecordingsTreeOutline.element);
        }

        const subtitle = null;
        let recordingTreeElement = new WI.GeneralTreeElement(["recording"], recording.displayName, subtitle, recording);
        recordingTreeElement.selectable = false;
        this._savedRecordingsTreeOutline.appendChild(recordingTreeElement);
    }

    _handleRecordingAutoCaptureInput(event)
    {
        let frameCount = this._updateRecordingAutoCaptureInputElementSize();
        this._recordingAutoCaptureNavigationItem.checked = !!frameCount;

        this._setRecordingAutoCaptureFrameCount(frameCount);
    }

    _handleRecordingAutoCaptureCheckedDidChange(event)
    {
        this._setRecordingAutoCaptureFrameCount(this._recordingAutoCaptureFrameCountInputElementValue || 0);
    }

    _handleCanvasRecordingAutoCaptureEnabledChanged(event)
    {
        this._recordingAutoCaptureNavigationItem.checked = WI.settings.canvasRecordingAutoCaptureEnabled.value;
    }

    _handleCanvasRecordingAutoCaptureFrameCountChanged(event)
    {
        // Only update the value if it is different to prevent mangling the selection.
        if (this._recordingAutoCaptureFrameCountInputElementValue !== WI.settings.canvasRecordingAutoCaptureFrameCount.value)
            this._recordingAutoCaptureFrameCountInputElementValue = WI.settings.canvasRecordingAutoCaptureFrameCount.value;

        this._updateRecordingAutoCaptureCheckboxLabel(WI.settings.canvasRecordingAutoCaptureFrameCount.value);
    }

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

    _handleRecordingSaved(event)
    {
        this._addSavedRecording(event.data.recording);
    }

    _handleSavedRecordingClicked(event)
    {
        WI.showRepresentedObject(event.data.treeElement.representedObject);
    }
};
