/*
 * 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.AuditNavigationSidebarPanel = class AuditNavigationSidebarPanel extends WI.NavigationSidebarPanel
{
    constructor()
    {
        super("audit", WI.UIString("Audits"));
    }

    // Static

    static _createNavigationItemTitle()
    {
        return WI.UIString("Create", "Create @ Audit Tab Navigation Sidebar", "Title of button that creates a new audit.");
    }

    // Public

    showDefaultContentView()
    {
        let contentView = new WI.ContentView;

        if (WI.auditManager.editing) {
            let contentPlaceholder = WI.createMessageTextView(WI.UIString("Editing audits"));
            contentView.element.appendChild(contentPlaceholder);

            let descriptionElement = contentPlaceholder.appendChild(document.createElement("div"));
            descriptionElement.className = "description";
            descriptionElement.textContent = WI.UIString("Select an audit in the navigation sidebar to edit it.");

            let createAuditNavigationItem = new WI.ButtonNavigationItem("create-audit", WI.AuditNavigationSidebarPanel._createNavigationItemTitle(), "Images/Plus15.svg", 15, 15);
            createAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
            createAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateButtonNavigationItemClicked, this);

            let createAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to create a new audit."), createAuditNavigationItem);
            createAuditHelpElement.classList.add("create-audit");
            contentPlaceholder.appendChild(createAuditHelpElement);

            let stopEditingAuditsNavigationItem = new WI.ButtonNavigationItem("stop-editing-audits", WI.UIString("Done"));
            stopEditingAuditsNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);

            let stopEditingAuditsHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop editing audits."), stopEditingAuditsNavigationItem);
            stopEditingAuditsHelpElement.classList.add("stop-editing-audits");
            contentPlaceholder.appendChild(stopEditingAuditsHelpElement);
        } else {
            let hasEnabledAudit = WI.auditManager.tests.length && WI.auditManager.tests.some((test) => !test.disabled && test.supported);

            let contentPlaceholder = WI.createMessageTextView(WI.UIString("No audit selected"));
            contentView.element.appendChild(contentPlaceholder);

            if (hasEnabledAudit) {
                let descriptionElement = contentPlaceholder.appendChild(document.createElement("div"));
                descriptionElement.className = "description";
                descriptionElement.textContent = WI.UIString("Select an audit in the navigation sidebar to view its results.");
            }

            let importAuditNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15);
            importAuditNavigationItem.title = WI.UIString("Import audit or result");
            importAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
            importAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);

            let importAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to import an audit or a result."), importAuditNavigationItem);
            importAuditHelpElement.classList.add("import-audit");
            contentPlaceholder.appendChild(importAuditHelpElement);

            let startEditingAuditsNavigationItem = new WI.ButtonNavigationItem("start-editing-audits", WI.UIString("Edit"));
            startEditingAuditsNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);

            let startEditingAuditsHelpElement = WI.createNavigationItemHelp(hasEnabledAudit ? WI.UIString("Press %s to start editing audits.") : WI.UIString("Press %s to enable audits."), startEditingAuditsNavigationItem);
            startEditingAuditsHelpElement.classList.add("start-editing-audits");
            contentPlaceholder.appendChild(startEditingAuditsHelpElement);
        }

        let versionContainer = contentView.element.appendChild(document.createElement("div"));
        versionContainer.classList.add("audit-version");

        let version = WI.AuditTestBase.Version;
        if (InspectorBackend.hasDomain("Audit"))
            version = Math.min(version, InspectorBackend.getVersion("Audit"));
        versionContainer.textContent = WI.UIString("Audit version: %s").format(version);

        versionContainer.appendChild(WI.auditManager.editing ? WI.ReferencePage.AuditTab.EditingAudits.createLinkElement() : WI.ReferencePage.AuditTab.createLinkElement());

        this.contentBrowser.showContentView(contentView);
    }

    // Popover delegate

    willDismissPopover(popover)
    {
        console.assert(popover instanceof WI.CreateAuditPopover, popover);

        let audit = popover.audit;
        if (!audit) {
            InspectorFrontendHost.beep();
            return;
        }

        WI.auditManager.addTest(audit, {save: true});

        WI.showRepresentedObject(audit);
    }

    // Protected

    initialLayout()
    {
        super.initialLayout();

        this.contentTreeOutline.allowsRepeatSelection = false;

        let controlsNavigationBar = new WI.NavigationBar;

        this._startStopButtonNavigationItem = new WI.ToggleButtonNavigationItem("start-stop-audit", WI.UIString("Start"), WI.UIString("Stop"), "Images/AuditStart.svg", "Images/AuditStop.svg", 13, 13);
        this._startStopButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        this._startStopButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleStartStopButtonNavigationItemClicked, this);
        controlsNavigationBar.addNavigationItem(this._startStopButtonNavigationItem);

        this._createButtonNavigationItem = new WI.ButtonNavigationItem("create-audit", WI.AuditNavigationSidebarPanel._createNavigationItemTitle(), "Images/Plus15.svg", 15, 15);
        this._createButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        this._createButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateButtonNavigationItemClicked, this);
        controlsNavigationBar.addNavigationItem(this._createButtonNavigationItem);

        controlsNavigationBar.addNavigationItem(new WI.DividerNavigationItem);

        let importButtonNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15);
        importButtonNavigationItem.title = WI.UIString("Import audit or result");
        importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
        importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
        controlsNavigationBar.addNavigationItem(importButtonNavigationItem);

        this.addSubview(controlsNavigationBar);

        this._editButtonNavigationItem = new WI.ActivateButtonNavigationItem("edit-audits", WI.UIString("Edit"), WI.UIString("Done"));
        this._editButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);
        this.filterBar.addFilterNavigationItem(this._editButtonNavigationItem);

        for (let test of WI.auditManager.tests)
            this._addTest(test);

        WI.auditManager.results.forEach((result, i) => {
            this._addResult(result, i);
        });

        this._updateControlNavigationItems();
        this._updateEditNavigationItems();
        this._updateNoAuditsPlaceholder();

        WI.AuditTestGroup.addEventListener(WI.AuditTestGroup.Event.TestRemoved, this._handleAuditTestRemoved, this);

        WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleAuditManagerEditingChanged, this);
        WI.auditManager.addEventListener(WI.AuditManager.Event.RunningStateChanged, this._handleAuditManagerRunningStateChanged, this);
        WI.auditManager.addEventListener(WI.AuditManager.Event.TestAdded, this._handleAuditTestAdded, this);
        WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditTestCompleted, this);
        WI.auditManager.addEventListener(WI.AuditManager.Event.TestRemoved, this._handleAuditTestRemoved, this);
        WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditTestScheduled, this);

        this.contentTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
    }

    closed()
    {
        super.closed();

        if (this.didInitialLayout) {
            WI.auditManager.removeEventListener(WI.AuditManager.Event.EditingChanged, this._handleAuditManagerEditingChanged, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.RunningStateChanged, this._handleAuditManagerRunningStateChanged, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.TestAdded, this._handleAuditTestAdded, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditTestCompleted, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.TestRemoved, this._handleAuditTestRemoved, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditTestScheduled, this);
        }
    }

    updateFilter()
    {
        super.updateFilter();

        if (!this.hasActiveFilters)
            this._updateNoAuditsPlaceholder();
    }

    hasCustomFilters()
    {
        return true;
    }

    matchTreeElementAgainstCustomFilters(treeElement, flags)
    {
        if (WI.auditManager.editing) {
            if (treeElement.representedObject instanceof WI.AuditTestResultBase || treeElement.hasAncestor(this._resultsFolderTreeElement) || treeElement === this._resultsFolderTreeElement)
                return false;
        } else {
            if (treeElement.representedObject instanceof WI.AuditTestBase && (treeElement.representedObject.disabled || !treeElement.representedObject.supported))
                return false;
        }

        return super.matchTreeElementAgainstCustomFilters(treeElement, flags);
    }

    // Private

    _addTest(test)
    {
        let treeElement = new WI.AuditTreeElement(test);

        if (this._resultsFolderTreeElement) {
            this.contentTreeOutline.insertChild(treeElement, this.contentTreeOutline.children.indexOf(this._resultsFolderTreeElement));
            this._resultsFolderTreeElement.hidden = !this._resultsFolderTreeElement.children.length || WI.auditManager.editing;
        } else
            this.contentTreeOutline.appendChild(treeElement);
    }

    _addResult(result, index)
    {
        this.element.classList.add("has-results");

        if (!this._resultsFolderTreeElement) {
            this._resultsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Results"));
            this.contentTreeOutline.appendChild(this._resultsFolderTreeElement);
        }

        this._resultsFolderTreeElement.expand();

        let resultFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Run %d").format(index + 1));
        if (result instanceof WI.AuditTestResultBase) {
            resultFolderTreeElement.subtitle = WI.UIString("Imported");
            result = [result];
        }
        this._resultsFolderTreeElement.appendChild(resultFolderTreeElement);

        console.assert(this._resultsFolderTreeElement.children.length === WI.auditManager.results.length);

        for (let resultItem of result)
            resultFolderTreeElement.appendChild(new WI.AuditTreeElement(resultItem));
    }

    _updateControlNavigationItems()
    {
        this._startStopButtonNavigationItem.toggled = WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping;
        this._startStopButtonNavigationItem.enabled = WI.auditManager.tests.some((test) => !test.disabled && test.supported) && (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive || WI.auditManager.runningState === WI.AuditManager.RunningState.Active);
        this._startStopButtonNavigationItem.hidden = WI.auditManager.editing;

        this._createButtonNavigationItem.hidden = !WI.auditManager.editing;
    }

     _updateEditNavigationItems()
    {
        this._editButtonNavigationItem.label = WI.auditManager.editing ? this._editButtonNavigationItem.activatedToolTip : this._editButtonNavigationItem.defaultToolTip;
        this._editButtonNavigationItem.activated = WI.auditManager.editing;
        this._editButtonNavigationItem.enabled = WI.auditManager.editing || WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive;
    }

    _updateNoAuditsPlaceholder()
    {
        if (WI.auditManager.editing || WI.auditManager.tests.some((test) => !test.disabled && test.supported)) {
            if (!this.hasActiveFilters)
                this.hideEmptyContentPlaceholder();
            return;
        }

        let contentPlaceholder = this.showEmptyContentPlaceholder(WI.UIString("No Enabled Audits"));
        contentPlaceholder.classList.add("no-enabled-audits");

        if (WI.auditManager.results.length) {
            // Move the placeholder to be the first element in the content area, where it will
            // be styled so that it doesn't obstruct the results elements.
            this.contentView.element.insertBefore(contentPlaceholder, this.contentView.element.firstChild);
        }
    }

    _handleAuditManagerEditingChanged(event)
    {
        let previousSelectedTreeElement = this.contentTreeOutline.selectedTreeElement;
        if (previousSelectedTreeElement) {
            if (WI.auditManager.editing) {
                if (!(previousSelectedTreeElement.representedObject instanceof WI.AuditTestBase))
                    previousSelectedTreeElement.deselect();
            } else {
                if (previousSelectedTreeElement.representedObject.disabled || !previousSelectedTreeElement.representedObject.supported)
                    previousSelectedTreeElement.deselect();
            }
        }

        this.updateFilter();

        if (!this.contentTreeOutline.selectedTreeElement)
            this.showDefaultContentView();

        this._updateControlNavigationItems();
        this._updateEditNavigationItems();
        this._updateNoAuditsPlaceholder();
    }

    _handleAuditManagerRunningStateChanged(event)
    {
        this._updateControlNavigationItems();
        this._updateEditNavigationItems();
    }

    _handleAuditTestAdded(event)
    {
        let {test} = event.data;

        this._addTest(test);

        this._updateControlNavigationItems();
        this._updateNoAuditsPlaceholder();
    }

    _handleAuditTestCompleted(event)
    {
        let {result, index} = event.data;
        this._addResult(result, index);

        this._updateControlNavigationItems();
        this._updateEditNavigationItems();
    }

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

        let {test} = event.data;

        let treeElement = this.treeElementForRepresentedObject(test);
        treeElement.parent.removeChild(treeElement);

        this._updateControlNavigationItems();
    }

    _handleAuditTestScheduled(event)
    {
        this._updateControlNavigationItems();
        this._updateEditNavigationItems();
    }

    _treeSelectionDidChange(event)
    {
        if (!this.selected)
            return;

        let treeElement = this.contentTreeOutline.selectedTreeElement;
        if (!treeElement || treeElement instanceof WI.FolderTreeElement) {
            this.showDefaultContentView();
            return;
        }

        let representedObject = treeElement.representedObject;
        if (representedObject instanceof WI.AuditTestCase || representedObject instanceof WI.AuditTestGroup
            || representedObject instanceof WI.AuditTestCaseResult || representedObject instanceof WI.AuditTestGroupResult) {
            WI.showRepresentedObject(representedObject);
            return;
        }

        console.error("Unknown tree element", treeElement);
    }

    _handleStartStopButtonNavigationItemClicked(event)
    {
        if (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive)
            WI.auditManager.start();
        else if (WI.auditManager.runningState === WI.AuditManager.RunningState.Active)
            WI.auditManager.stop();
    }

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

        let popover = new WI.CreateAuditPopover(this);
        popover.show(event.target.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MAX_X, WI.RectEdge.MIN_X]);
    }

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

    _handleEditButtonNavigationItemClicked(event)
    {
        WI.auditManager.editing = !WI.auditManager.editing;
    }
};
