/*
 * 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.element.classList.toggle("contains-test-case", this._subobjects().some((test) => test instanceof WI.AuditTestCase || test instanceof WI.AuditTestCaseResult));
        this.element.classList.toggle("contains-test-group", this._subobjects().some((test) => test instanceof WI.AuditTestGroup || test instanceof WI.AuditTestGroupResult));

        this._levelScopeBar = null;
    }

    // Protected

    initialLayout()
    {
        super.initialLayout();

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

        let nameElement = informationContainer.appendChild(document.createElement("h1"));
        nameElement.textContent = this.representedObject.name;

        if (this.representedObject.description) {
            let descriptionElement = informationContainer.appendChild(document.createElement("p"));
            descriptionElement.textContent = this.representedObject.description;
        }

        this._levelNavigationBar = new WI.NavigationBar(document.createElement("nav"));
        this._levelNavigationBar.element.dataset.prefix = WI.UIString("Showing:");
        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;
        });
    }

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

        super.layout();

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

    shown()
    {
        super.shown();

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

        for (let subobject of this._subobjects()) {
            if (subobject instanceof WI.AuditTestBase && subobject.disabled)
                continue;

            let view = WI.ContentView.contentViewForRepresentedObject(subobject);
            this.contentView.addSubview(view);
            view.shown();
        }
    }

    hidden()
    {
        for (let view of this.contentView.subviews)
            view.hidden();

        this.contentView.removeAllSubviews();

        super.hidden();
    }

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

        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 [];
    }

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

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

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

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

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