/*
 * Copyright (C) 2018 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.AuditTestContentView = class AuditTestContentView extends WI.ContentView
{
    constructor(representedObject)
    {
        console.assert(representedObject instanceof WI.AuditTestBase || representedObject instanceof WI.AuditTestResultBase);

        super(representedObject);

        // This class should not be instantiated directly. Create a concrete subclass instead.
        console.assert(this.constructor !== WI.AuditTestContentView && this instanceof WI.AuditTestContentView);

        this.element.classList.add("audit-test");
        if (this.representedObject.editable)
            this.element.classList.add("editable");

        if (this.representedObject instanceof WI.AuditTestBase) {
            this._exportTestButtonNavigationItem = new WI.ButtonNavigationItem("audit-export-test", WI.UIString("Export Audit"), "Images/Export.svg", 15, 15);
            this._exportTestButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
            this._exportTestButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
            this._exportTestButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleExportTestButtonNavigationItemClicked, this);
        }

        this._exportResultButtonNavigationItem = new WI.ButtonNavigationItem("audit-export-result", WI.UIString("Export Result"), "Images/Export.svg", 15, 15);
        this._exportResultButtonNavigationItem.tooltip = WI.UIString("Export result (%s)", "Export result (%s) @ Audit Tab", "Tooltip for button that exports the most recent result after running an audit.").format(WI.saveKeyboardShortcut.displayName);
        this._exportResultButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        this._exportResultButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        this._exportResultButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleExportResultButtonNavigationItemClicked, this);

        this._updateExportNavigationItems();

        this._headerView = new WI.View(document.createElement("header"));
        this._contentView = new WI.View(document.createElement("section"));
        this._placeholderElement = null;

        this._cachedName = this.representedObject.name;
        this._nameElement = null;

        this._descriptionElement = null;

        this._supportsInputElement = null;
        this._supportsWarningElement = null;

        this._shownResult = null;
    }

    // Public

    get navigationItems()
    {
        let navigationItems = [];
        if (this._exportTestButtonNavigationItem)
            navigationItems.push(this._exportTestButtonNavigationItem);
        navigationItems.push(this._exportResultButtonNavigationItem);
        return navigationItems;
    }

    // Protected

    get headerView() { return this._headerView; }
    get contentView() { return this._contentView; }

    get supportsSave()
    {
        return !WI.auditManager.editing && !!this.representedObject.result;
    }

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

    get result()
    {
        if (this.representedObject instanceof WI.AuditTestBase)
            return this.representedObject;
        return this.representedObject.result;
    }

    createNameElement(tagName)
    {
        console.assert(!this._nameElement);

        this._nameElement = document.createElement(tagName);
        this._nameElement.textContent = this.representedObject.name;
        this._nameElement.className = "name";

        if (this.representedObject.editable) {
            this._nameElement.spellcheck = false;

            this._nameElement.addEventListener("keydown", (event) => {
                this._handleEditorKeydown(event, this._descriptionElement);
            });

            this._nameElement.addEventListener("input", (event) => {
                console.assert(WI.auditManager.editing);

                let name = this._nameElement.textContent;
                if (!name.trim()) {
                    name = this._cachedName;
                    this._nameElement.removeChildren();
                }
                this.representedObject.name = name;
            });
        }

        return this._nameElement;
    }

    createDescriptionElement(tagName)
    {
        console.assert(!this._descriptionElement);

        this._descriptionElement = document.createElement(tagName);
        this._descriptionElement.textContent = this.representedObject.description;
        this._descriptionElement.className = "description";

        if (this.representedObject.editable) {
            this._descriptionElement.spellcheck = false;

            this._descriptionElement.addEventListener("keydown", (event) => {
                this._handleEditorKeydown(event, this._supportsInputElement);
            });

            this._descriptionElement.addEventListener("input", (event) => {
                console.assert(WI.auditManager.editing);

                let description = this._descriptionElement.textContent;
                if (!description.trim()) {
                    description = "";
                    this._descriptionElement.removeChildren();
                }
                this.representedObject.description = description;
            });
        }

        return this._descriptionElement;
    }

    createControlsTableElement()
    {
        console.assert(this.representedObject instanceof WI.AuditTestBase);
        console.assert(!this._supportsInputElement);
        console.assert(!this._supportsWarningElement);

        let controlsTableElement = document.createElement("table");
        controlsTableElement.className = "controls";

        let supportsRowElement = controlsTableElement.appendChild(document.createElement("tr"));
        supportsRowElement.className = "supports";

        let supportsHeaderElement = supportsRowElement.appendChild(document.createElement("th"));
        supportsHeaderElement.textContent = WI.unlocalizedString("supports");

        let supportsDataElement = supportsRowElement.appendChild(document.createElement("td"));

        this._supportsInputElement = supportsDataElement.appendChild(document.createElement("input"));
        this._supportsInputElement.type = "number";
        this._supportsInputElement.disabled = !this.representedObject.editable;
        this._supportsInputElement.min = 0;
        this._supportsInputElement.placeholder = Math.min(WI.AuditTestBase.Version, InspectorBackend.hasDomain("Audit") ? InspectorBackend.getVersion("Audit") : Infinity);
        if (!isNaN(this.representedObject.supports))
            this._supportsInputElement.value = this.representedObject.supports;

        if (this.representedObject.editable) {
            this._supportsInputElement.addEventListener("keydown", (event) => {
                this._handleEditorKeydown(event, this._setupEditorElement);
            });
        }

        this._supportsWarningElement = supportsDataElement.appendChild(document.createElement("span"));
        this._supportsWarningElement.className = "warning";

        if (this.representedObject.topLevelTest === this.representedObject) {
            let setupRowElement = controlsTableElement.appendChild(document.createElement("tr"));
            setupRowElement.className = "setup";

            let setupHeaderElement = setupRowElement.appendChild(document.createElement("th"));
            setupHeaderElement.textContent = WI.unlocalizedString("setup");

            let setupDataElement = setupRowElement.appendChild(document.createElement("td"));

            this._setupEditorElement = setupDataElement.appendChild(document.createElement("div"));
        }

        if (this.representedObject.editable) {
            this._supportsInputElement.addEventListener("input", (event) => {
                this.representedObject.supports = parseInt(this._supportsInputElement.value);

                this._updateSupportsInputState();
            });
        }

        return controlsTableElement;
    }

    initialLayout()
    {
        super.initialLayout();

        this.addSubview(this._headerView);
        this.addSubview(this._contentView);
    }

    layout()
    {
        super.layout();

        if (this.representedObject instanceof WI.AuditTestBase) {
            this.element.classList.toggle("unsupported", !this.representedObject.supported);
            this.element.classList.toggle("disabled", this.representedObject.disabled);
            this.element.classList.toggle("manager-editing", WI.auditManager.editing);

            if (this.representedObject.editable) {
                let contentEditable = WI.auditManager.editing ? "plaintext-only" : "inherit";
                this._nameElement.contentEditable = contentEditable;
                this._descriptionElement.contentEditable = contentEditable;
            }

            if (WI.auditManager.editing) {
                this._cachedName = this.representedObject.name;
                this._nameElement.dataset.name = this._cachedName;

                this._updateSupportsInputState();
                this._createSetupEditor();
            } else {
                this._nameElement.textContent ||= this._cachedName;

                this._setupEditorElement?.removeChildren();
            }
        }

        this.hidePlaceholder();
        this._updateExportNavigationItems();
    }

    attached()
    {
        super.attached();

        if (this.representedObject instanceof WI.AuditTestBase) {
            this.representedObject.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.ResultChanged, this.handleResultChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.Stopping, this._handleTestChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this);

            WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleEditingChanged, this);
        }
    }

    detached()
    {
        if (this.representedObject instanceof WI.AuditTestBase) {
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.Completed, this._handleTestChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.Progress, this._handleTestChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.ResultChanged, this.handleResultChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.Stopping, this._handleTestChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this);

            WI.auditManager.removeEventListener(WI.AuditManager.Event.EditingChanged, this._handleEditingChanged, this);
            if (this.representedObject.editable && WI.auditManager.editing)
                this.saveEditedData();
        }

        super.detached();
    }

    handleResultChanged(event)
    {
        // Overridden by sub-classes.

        if (!WI.auditManager.editing)
            this.needsLayout();
    }

    get placeholderElement()
    {
        return this._placeholderElement;
    }

    set placeholderElement(placeholderElement)
    {
        this.hidePlaceholder();

        this._placeholderElement = placeholderElement;
    }

    saveEditedData()
    {
        console.assert(this.representedObject.editable, this.representedObject);
        if (this._setupCodeMirror)
            this.representedObject.setup = this._setupCodeMirror.getValue().trim();
    }

    showRunningPlaceholder()
    {
        // Overridden by sub-classes.

        console.assert(this.placeholderElement);

        this._showPlaceholder();
    }

    showStoppingPlaceholder()
    {
        if (!this.placeholderElement || !this.placeholderElement.__placeholderStopping) {
            this.placeholderElement = WI.createMessageTextView(WI.UIString("Stopping the \u201C%s\u201D audit").format(this.representedObject.name));
            this.placeholderElement.__placeholderStopping = true;

            let spinner = new WI.IndeterminateProgressSpinner;
            this.placeholderElement.appendChild(spinner.element);

            this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab"));
        }

        this._showPlaceholder();
    }

    showNoResultPlaceholder()
    {
        if (!this.placeholderElement || !this.placeholderElement.__placeholderNoResult) {
            this.placeholderElement = WI.createMessageTextView(WI.UIString("No Result"));
            this.placeholderElement.__placeholderNoResult = true;

            let startNavigationItem = new WI.ButtonNavigationItem("run-audit", WI.UIString("Start"), "Images/AuditStart.svg", 15, 15);
            startNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
            startNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, function(event) {
                WI.auditManager.start([this.representedObject]);
            }, this);

            let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to start running the audit."), startNavigationItem);
            this.placeholderElement.appendChild(importHelpElement);

            this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab"));
        }

        this._showPlaceholder();
    }

    showNoResultDataPlaceholder()
    {
        if (!this.placeholderElement || !this.placeholderElement.__placeholderNoResultData) {
            let result = this.representedObject.result;
            if (!result) {
                this.showNoResultPlaceholder();
                return;
            }

            let message = null;
            if (result.didError)
                message = WI.UIString("The \u201C%s\u201D audit threw an error");
            else if (result.didFail)
                message = WI.UIString("The \u201C%s\u201D audit failed");
            else if (result.didWarn)
                message = WI.UIString("The \u201C%s\u201D audit resulted in a warning");
            else if (result.didPass)
                message = WI.UIString("The \u201C%s\u201D audit passed");
            else if (result.unsupported)
                message = WI.UIString("The \u201C%s\u201D audit is unsupported");
            else {
                console.error("Unknown result", result);
                return;
            }

            this.placeholderElement = WI.createMessageTextView(message.format(this.representedObject.name), result.didError);
            this.placeholderElement.__placeholderNoResultData = true;

            this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab"));
        }

        this._showPlaceholder();
    }

    showFilteredPlaceholder()
    {
        if (!this.placeholderElement || !this.placeholderElement.__placeholderFiltered) {
            this.placeholderElement = WI.createMessageTextView(WI.UIString("No Filter Results"));
            this.placeholderElement.__placeholderFiltered = true;

            let buttonElement = this.placeholderElement.appendChild(document.createElement("button"));
            buttonElement.textContent = WI.UIString("Clear Filters");
            buttonElement.addEventListener("click", () => {
                this.resetFilter();
                this.needsLayout();
            });

            this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab"));
        }

        this._showPlaceholder();
    }

    hidePlaceholder()
    {
        this.element.classList.remove("showing-placeholder");
        if (this.placeholderElement)
            this.placeholderElement.remove();
    }

    applyFilter(levels)
    {
        let hasMatch = false;
        for (let view of this.contentView.subviews) {
            let matches = view.applyFilter(levels);
            view.element.classList.toggle("filtered", !matches);

            if (matches)
                hasMatch = true;
        }

        this.element.classList.toggle("no-matches", !hasMatch);

        if (!Array.isArray(levels))
            return true;

        let result = this.representedObject.result;
        if (!result)
            return false;

        if ((levels.includes(WI.AuditTestCaseResult.Level.Error) && result.didError)
            || (levels.includes(WI.AuditTestCaseResult.Level.Fail) && result.didFail)
            || (levels.includes(WI.AuditTestCaseResult.Level.Warn) && result.didWarn)
            || (levels.includes(WI.AuditTestCaseResult.Level.Pass) && result.didPass)
            || (levels.includes(WI.AuditTestCaseResult.Level.Unsupported) && result.unsupported)) {
            return true;
        }

        return false;
    }

    resetFilter()
    {
        for (let view of this.contentView.subviews)
            view.element.classList.remove("filtered");

        this.element.classList.remove("no-matches");
    }

    // Private

    _exportResult()
    {
        WI.auditManager.export(this.representedObject.result);
    }

    _updateExportNavigationItems()
    {
        if (this._exportTestButtonNavigationItem)
            this._exportTestButtonNavigationItem.enabled = !WI.auditManager.editing;

        this._exportResultButtonNavigationItem.enabled = !WI.auditManager.editing && this.representedObject.result;
    }

    _updateSupportsInputState()
    {
        console.assert(WI.auditManager.editing);

        this._supportsInputElement.autosize(4);

        this._supportsWarningElement.removeChildren();
        if (this.representedObject.supports > WI.AuditTestBase.Version)
            this._supportsWarningElement.textContent = WI.UIString("too new to run in this Web Inspector", "too new to run in this Web Inspector @ Audit Tab", "Warning text shown if the version number in the 'supports' input is too new.");
        else if (InspectorBackend.hasDomain("Audit") && this._supports > InspectorBackend.getVersion("Audit"))
            this._supportsWarningElement.textContent = WI.UIString("too new to run in the inspected page", "too new to run in the inspected page @ Audit Tab", "Warning text shown if the version number in the 'supports' input is too new.");
    }

    _createSetupEditor()
    {
        if (!this._setupEditorElement)
            return;

        let setupEditorElement = document.createElement(this._setupEditorElement.nodeName);
        setupEditorElement.className = "editor";

        // Give the rest of the view a chance to load.
        setTimeout(() => {
            this._setupCodeMirror = WI.CodeMirrorEditor.create(setupEditorElement, {
                autoCloseBrackets: true,
                lineNumbers: true,
                lineWrapping: true,
                matchBrackets: true,
                mode: "text/javascript",
                readOnly: this.representedObject.editable ? false : "nocursor",
                styleSelectedText: true,
                value: this.representedObject.setup,
            });
        });

        this._setupEditorElement.parentNode.replaceChild(setupEditorElement, this._setupEditorElement);
        this._setupEditorElement = setupEditorElement;
    }

    _showPlaceholder()
    {
        this.element.classList.add("showing-placeholder");
        this.contentView.element.appendChild(this.placeholderElement);
    }

    _handleEditorKeydown(event, nextEditor)
    {
        console.assert(WI.auditManager.editing);

        switch (event.keyCode) {
        case WI.KeyboardShortcut.Key.Enter.keyCode:
            if (nextEditor) {
                nextEditor.focus();
                break;
            }
            // fallthrough

        case WI.KeyboardShortcut.Key.Escape.keyCode:
            event.target.blur();
            break;

        default:
            return;
        }

        event.preventDefault();
    }

    _handleExportTestButtonNavigationItemClicked(event)
    {
        WI.auditManager.export(this.representedObject);
    }

    _handleExportResultButtonNavigationItemClicked(event)
    {
        this._exportResult();
    }

    _handleTestChanged(event)
    {
        this.needsLayout();
    }

    _handleTestDisabledChanged(event)
    {
        console.assert(WI.auditManager.editing);

        this.element.classList.toggle("disabled", this.representedObject.disabled);
    }

    _handleTestSupportedChanged(event)
    {
        console.assert(WI.auditManager.editing);

        this.element.classList.toggle("unsupported", !this.representedObject.supported);
    }

    _handleEditingChanged(event)
    {
        this.needsLayout();

        // We only need to save changes when editing is done. No need to save it after entering the editing mode.
        if (!WI.auditManager.editing && this.representedObject.editable)
            this.saveEditedData();

        this._updateExportNavigationItems();
    }
};
