/*
 * 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.AuditTestGroupContentView = class AuditTestGroupContentView extends WI.AuditTestContentView
{
    constructor(representedObject)
    {
        console.assert(representedObject instanceof WI.AuditTestGroup || representedObject instanceof WI.AuditTestGroupResult);

        super(representedObject);

        this.element.classList.add("audit-test-group");

        this._levelScopeBar = null;

        this._viewForSubobject = new Map;
    }

    // Popover delegate

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

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

        this.representedObject.addTest(audit);
    }

    // Protected

    createControlsTableElement()
    {
        let controlsTableElement = super.createControlsTableElement();

        let actionsRowElement = controlsTableElement.appendChild(document.createElement("tr"));
        actionsRowElement.className = "actions";

        let actionsHeaderElement = controlsTableElement.appendChild(document.createElement("th"));
        let actionsDataElement = controlsTableElement.appendChild(document.createElement("td"));

        let addTestCaseButtonElement = actionsDataElement.appendChild(document.createElement("button"));
        addTestCaseButtonElement.disabled = !this.representedObject.editable;
        addTestCaseButtonElement.textContent = WI.UIString("Add Test Case", "Add Test Case @ Audit Tab - Group", "Text of button to add a new audit test case to the currently shown audit group.");
        addTestCaseButtonElement.addEventListener("click", (event) => {
            console.assert(WI.auditManager.editing);

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

        return controlsTableElement;
    }

    initialLayout()
    {
        super.initialLayout();

        let informationContainer = this.headerView.element.appendChild(document.createElement("div"));
        informationContainer.classList.add("information");

        let nameContainer = informationContainer.appendChild(document.createElement("h1"));

        nameContainer.appendChild(this.createNameElement("span"));

        informationContainer.appendChild(this.createDescriptionElement("p"));

        if (this.representedObject instanceof WI.AuditTestGroup)
            informationContainer.appendChild(this.createControlsTableElement());

        this._levelNavigationBar = new WI.NavigationBar(document.createElement("nav"));
        this.headerView.addSubview(this._levelNavigationBar);

        this._percentageContainer = this.headerView.element.appendChild(document.createElement("div"));
        this._percentageContainer.classList.add("percentage-pass");
        this._percentageContainer.hidden = true;

        this._percentageTextElement = document.createElement("span");

        const format = WI.UIString("%s%%", "Percentage (of audits)", "The number of tests that passed expressed as a percentage, followed by a literal %.");
        String.format(format, [this._percentageTextElement], String.standardFormatters, this._percentageContainer, (a, b) => {
            a.append(b);
            return a;
        });

        this._updateClassList();
    }

    layout()
    {
        if (this.layoutReason !== WI.View.LayoutReason.Dirty)
            return;

        super.layout();

        if (WI.auditManager.editing) {
            if (this._levelScopeBar) {
                this._levelNavigationBar.removeNavigationItem(this._levelScopeBar);
                this._levelScopeBar = null;
            }

            this._percentageContainer.hidden = true;

            this.resetFilter();
            return;
        }

        let result = this.representedObject.result;
        if (!result) {
            if (this._levelScopeBar) {
                this._levelNavigationBar.removeNavigationItem(this._levelScopeBar);
                this._levelScopeBar = null;
            }

            this._percentageContainer.hidden = true;
            this._percentageTextElement.textContent = "";

            if (this.representedObject.runningState === WI.AuditManager.RunningState.Inactive)
                this.showNoResultPlaceholder();
            else if (this.representedObject.runningState === WI.AuditManager.RunningState.Active)
                this.showRunningPlaceholder();
            else if (this.representedObject.runningState === WI.AuditManager.RunningState.Stopping)
                this.showStoppingPlaceholder();

            return;
        }

        let levelCounts = result.levelCounts;
        let totalCount = Object.values(levelCounts).reduce((accumulator, current) => accumulator + current);
        this._percentageTextElement.textContent = Math.floor(100 * levelCounts[WI.AuditTestCaseResult.Level.Pass] / totalCount);
        this._percentageContainer.hidden = false;

        if (!this._levelScopeBar) {
            let scopeBarItems = [];

            let addScopeBarItem = (level, labelSingular, labelPlural) => {
                let count = levelCounts[level];
                if (isNaN(count) || count <= 0)
                    return;

                let label = (labelPlural && count !== 1) ? labelPlural : labelSingular;
                let scopeBarItem = new WI.ScopeBarItem(level, label.format(count), {
                    className: level,
                    exclusive: false,
                    independent: true,
                });
                scopeBarItem.selected = true;

                scopeBarItem.element.insertBefore(document.createElement("img"), scopeBarItem.element.firstChild);

                scopeBarItems.push(scopeBarItem);
            };

            addScopeBarItem(WI.AuditTestCaseResult.Level.Pass, WI.UIString("%d Passed", "%d Passed (singular)", ""), WI.UIString("%d Passed", "%d Passed (plural)", ""));
            addScopeBarItem(WI.AuditTestCaseResult.Level.Warn, WI.UIString("%d Warning"), WI.UIString("%d Warnings"));
            addScopeBarItem(WI.AuditTestCaseResult.Level.Fail, WI.UIString("%d Failed", "%d Failed (singular)", ""), WI.UIString("%d Failed", "%d Failed (plural)", ""));
            addScopeBarItem(WI.AuditTestCaseResult.Level.Error, WI.UIString("%d Error"), WI.UIString("%d Errors"));
            addScopeBarItem(WI.AuditTestCaseResult.Level.Unsupported, WI.UIString("%d Unsupported", "%d Unsupported (singular)", ""), WI.UIString("%d Unsupported", "%d Unsupported (plural)", ""));

            this._levelScopeBar = new WI.ScopeBar(null, scopeBarItems);
            this._levelScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleLevelScopeBarSelectionChanged, this);
            this._levelNavigationBar.addNavigationItem(this._levelScopeBar);
        }

        if (this.applyFilter())
            this.hidePlaceholder();
        else
            this.showFilteredPlaceholder();
    }

    attached()
    {
        super.attached();

        if (this.representedObject instanceof WI.AuditTestGroup) {
            this.representedObject.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestGroupProgress, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this);

            if (this.representedObject.editable) {
                this.representedObject.addEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this);
                this.representedObject.addEventListener(WI.AuditTestGroup.Event.TestRemoved, this._handleTestGroupTestRemoved, this);
            }
        }

        console.assert(!this._viewForSubobject.size);
        for (let subobject of this._subobjects())
            this._addTest(subobject);
    }

    detached()
    {
        if (this.representedObject instanceof WI.AuditTestGroup) {
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.Progress, this._handleTestGroupProgress, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this);

            if (this.representedObject.editable) {
                this.representedObject.removeEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this);
                this.representedObject.removeEventListener(WI.AuditTestGroup.Event.TestRemoved, this._handleTestGroupTestRemoved, this);
            }
        }

        this.contentView.removeAllSubviews();
        this._viewForSubobject.clear();

        super.detached();
    }

    applyFilter(levels)
    {
        if (this._levelScopeBar && !levels)
            levels = this._levelScopeBar.selectedItems.map((item) => item.id);

        this._updateLevelScopeBar(levels);

        return super.applyFilter(levels);
    }

    resetFilter()
    {
        this._updateLevelScopeBar(Object.values(WI.AuditTestCaseResult.Level));

        super.resetFilter();
    }

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

            this.placeholderElement.__progress = document.createElement("progress");
            this.placeholderElement.__progress.value = 0;
            this.placeholderElement.appendChild(this.placeholderElement.__progress);

            let stopAuditNavigationItem = new WI.ButtonNavigationItem("stop-audit", WI.UIString("Stop"), "Images/AuditStop.svg", 13, 13);
            stopAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
            stopAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, function(event) {
                WI.auditManager.stop();
            }, stopAuditNavigationItem);

            let stopAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop running."), stopAuditNavigationItem);
            this.placeholderElement.appendChild(stopAuditHelpElement);

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

        super.showRunningPlaceholder();
    }

    // Private

    _subobjects()
    {
        if (this.representedObject instanceof WI.AuditTestGroup)
            return this.representedObject.tests;

        if (this.representedObject instanceof WI.AuditTestGroupResult)
            return this.representedObject.results;

        console.error("Unknown representedObject", this.representedObject);
        return [];
    }

    _updateClassList()
    {
        let subobjects = this._subobjects();
        let containsTestGroup = subobjects.some((test) => test instanceof WI.AuditTestGroup || test instanceof WI.AuditTestGroupResult);
        this.element.classList.toggle("contains-test-group", containsTestGroup);
        this.element.classList.toggle("contains-test-case", !containsTestGroup && subobjects.some((test) => test instanceof WI.AuditTestCase || test instanceof WI.AuditTestCaseResult));
    }

    _updateLevelScopeBar(levels)
    {
        if (!this._levelScopeBar)
            return;

        for (let item of this._levelScopeBar.items)
            item.selected = levels.includes(item.id);

        for (let view of this._viewForSubobject.values()) {
            if (view instanceof WI.AuditTestGroupContentView)
                view._updateLevelScopeBar(levels);
        }
    }

    _addTest(test)
    {
        console.assert(!this._viewForSubobject.has(test));

        let view = WI.ContentView.contentViewForRepresentedObject(test);
        this.contentView.addSubview(view);

        this._viewForSubobject.set(test, view);
    }

    _handleTestGroupProgress(event)
    {
        let {index, count} = event.data;
        if (this.placeholderElement && this.placeholderElement.__progress)
            this.placeholderElement.__progress.value = (index + 1) / count;
    }

    _handleTestGroupScheduled(event)
    {
        if (this.placeholderElement && this.placeholderElement.__progress)
            this.placeholderElement.__progress.value = 0;
    }

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

        let {test} = event.data;

        this._addTest(test);

        this._updateClassList();
    }

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

        let {test} = event.data;

        let view = this._viewForSubobject.get(test);
        console.assert(view);

        this.contentView.removeSubview(view);

        this._updateClassList();
    }

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