/*
 * 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);
            });
            return;
        }

        canvas.requestNode().then((node) => {
            if (!node || !node.ownerDocument)
                return;
            node.highlight();
        });
    }

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