/*
 * 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.AuditTreeElement = class AuditTreeElement extends WI.GeneralTreeElement
{
    constructor(representedObject)
    {
        let isTestCase = representedObject instanceof WI.AuditTestCase;
        let isTestGroup = representedObject instanceof WI.AuditTestGroup;
        let isTestCaseResult = representedObject instanceof WI.AuditTestCaseResult;
        let isTestGroupResult = representedObject instanceof WI.AuditTestGroupResult;
        console.assert(isTestCase || isTestGroup || isTestCaseResult || isTestGroupResult);

        let classNames = ["audit"];
        if (isTestCase)
            classNames.push("test-case");
        else if (isTestGroup)
            classNames.push("test-group");
        else if (isTestCaseResult)
            classNames.push("test-case-result");
        else if (isTestGroupResult)
            classNames.push("test-group-result");

        let options = {
            hasChildren: isTestGroup || isTestGroupResult,
        };

        const subtitle = null;
        super(classNames, representedObject.name, subtitle, representedObject, options);

        if (isTestGroup)
            this._expandedSetting = new WI.Setting(WI.AuditTreeElement.expandedSettingKey(this.representedObject.name), false);
    }

    // Static

    static expandedSettingKey(name)
    {
        return `audit-tree-element-${name}-expanded`;
    }

    // Protected

    onattach()
    {
        super.onattach();

        if (this.representedObject instanceof WI.AuditTestBase) {
            this.representedObject.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this);
            this.representedObject.addEventListener(WI.AuditTestBase.Event.ResultChanged, this._handleTestResultChanged, this);

            if (this.representedObject instanceof WI.AuditTestCase)
                this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestCaseScheduled, this);
            else if (this.representedObject instanceof WI.AuditTestGroup)
                this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this);

            if (this.representedObject.editable) {
                this.representedObject.addEventListener(WI.AuditTestBase.Event.NameChanged, this._handleTestNameChanged, this);
                this.representedObject.addEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this);

                if (this.representedObject instanceof WI.AuditTestGroup)
                    this.representedObject.addEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this);
            }

            WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleManagerEditingChanged, this);
            WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
            WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);
        }

        if (this.representedObject.supported && this._expandedSetting && this._expandedSetting.value)
            this.expand();

        this._updateStatus();
    }

    ondetach()
    {
        if (this.representedObject instanceof WI.AuditTestBase) {
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this);
            this.representedObject.removeEventListener(WI.AuditTestBase.Event.ResultChanged, this._handleTestResultChanged, this);

            if (this.representedObject instanceof WI.AuditTestCase)
                this.representedObject.removeEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestCaseScheduled, this);
            else if (this.representedObject instanceof WI.AuditTestGroup)
                this.representedObject.removeEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this);

            if (this.representedObject.editable) {
                this.representedObject.removeEventListener(WI.AuditTestBase.Event.NameChanged, this._handleTestNameChanged, this);
                this.representedObject.removeEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this);

                if (this.representedObject instanceof WI.AuditTestGroup)
                    this.representedObject.removeEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this);
            }

            WI.auditManager.removeEventListener(WI.AuditManager.Event.EditingChanged, this._handleManagerEditingChanged, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
            WI.auditManager.removeEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);
        }

        super.ondetach();
    }

    onpopulate()
    {
        super.onpopulate();

        if (this.children.length && !this.shouldRefreshChildren)
            return;

        this.shouldRefreshChildren = false;

        this.removeChildren();

        if (this.representedObject instanceof WI.AuditTestGroup) {
            for (let test of this.representedObject.tests)
                this.appendChild(new WI.AuditTreeElement(test));
        } else if (this.representedObject instanceof WI.AuditTestGroupResult) {
            for (let result of this.representedObject.results)
                this.appendChild(new WI.AuditTreeElement(result));
        }
    }

    onexpand()
    {
        console.assert(this.expanded);

        if (this._expandedSetting)
            this._expandedSetting.value = this.expanded;
    }

    oncollapse()
    {
        console.assert(!this.expanded);

        if (this._expandedSetting)
            this._expandedSetting.value = this.expanded;
    }

    ondelete()
    {
        if (!(this.representedObject instanceof WI.AuditTestBase))
            return false;

        if (!WI.auditManager.editing)
            return false;

        this.representedObject.remove();

        return true;
    }

    canSelectOnMouseDown(event)
    {
        if (this.representedObject instanceof WI.AuditTestBase && this.representedObject.supported && this.status.contains(event.target))
            return false;

        return super.canSelectOnMouseDown(event);
    }

    populateContextMenu(contextMenu, event)
    {
        let isTest = this.representedObject instanceof WI.AuditTestBase;

        contextMenu.appendSeparator();

        if (WI.auditManager.editing) {
            if (isTest) {
                if (this.representedObject.supported) {
                    contextMenu.appendItem(this.representedObject.disabled ? WI.UIString("Enable Audit") : WI.UIString("Disable Audit"), () => {
                        this.representedObject.disabled = !this.representedObject.disabled;
                    });
                }

                contextMenu.appendItem(WI.UIString("Duplicate Audit"), async () => {
                    let audit = await this.representedObject.clone();
                    WI.auditManager.addTest(audit, {save: true});
                });

                if (this.representedObject.editable) {
                    contextMenu.appendItem(WI.UIString("Delete Audit"), () => {
                        this.representedObject.remove();
                    });
                }
            }
        } else {
            if (isTest) {
                contextMenu.appendItem(WI.UIString("Start Audit"), () => {
                    this._start();
                }, WI.auditManager.runningState !== WI.AuditManager.RunningState.Inactive);

                contextMenu.appendSeparator();

                contextMenu.appendItem(WI.UIString("Export Audit"), () => {
                    WI.auditManager.export(this.representedObject);
                });
            }

            contextMenu.appendItem(WI.UIString("Export Result"), () => {
                WI.auditManager.export(this.representedObject.result);
            }, !this.representedObject.result);

            if (isTest && this.representedObject.editable) {
                contextMenu.appendSeparator();

                contextMenu.appendItem(WI.UIString("Edit Audit"), () => {
                    WI.auditManager.editing = true;
                    WI.showRepresentedObject(this.representedObject);
                });
            }
        }

        contextMenu.appendSeparator();

        super.populateContextMenu(contextMenu, event);
    }

    // Private

    _start()
    {
        if (WI.auditManager.runningState !== WI.AuditManager.RunningState.Inactive)
            return;

        WI.auditManager.start([this.representedObject]);
    }

    _updateStatus()
    {
        if (this.representedObject instanceof WI.AuditTestBase && !this.representedObject.supported) {
            this.status = document.createElement("img");
            this.status.title = WI.UIString("This audit is not supported");
            this.addClassName("unsupported");
            return;
        }

        if (WI.auditManager.editing) {
            this.status = document.createElement("input");
            this.status.type = "checkbox";
            this._updateTestGroupDisabled();
            this.status.addEventListener("change", () => {
                this.representedObject.disabled = !this.representedObject.disabled;
            });

            this.addClassName("editing-audits");
            return;
        }

        let className = "";

        let result = this.representedObject.result;
        if (result) {
            if (result.didError)
                className = WI.AuditTestCaseResult.Level.Error;
            else if (result.didFail)
                className = WI.AuditTestCaseResult.Level.Fail;
            else if (result.didWarn)
                className = WI.AuditTestCaseResult.Level.Warn;
            else if (result.didPass)
                className = WI.AuditTestCaseResult.Level.Pass;
            else if (result.unsupported)
                className = WI.AuditTestCaseResult.Level.Unsupported;
        }

        this.status = document.createElement("img");

        if (this.representedObject instanceof WI.AuditTestBase) {
            this.status.title = WI.UIString("Start");
            this.status.addEventListener("click", this._handleStatusClick.bind(this));

            if (!className)
                className = "show-on-hover";
        }

        this.status.classList.add(className);

        this.removeClassName("editing-audits");
    }

    _showRunningSpinner()
    {
        if (this.representedObject.runningState === WI.AuditManager.RunningState.Inactive) {
            this._updateStatus();
            return;
        }

        if (!this.status || !this.status.__spinner) {
            let spinner = new WI.IndeterminateProgressSpinner;
            this.status = spinner.element;
            this.status.__spinner = true;
        }
    }

    _showRunningProgress(progress)
    {
        if (!this.representedObject.runningState === WI.AuditManager.RunningState.Inactive) {
            this._updateStatus();
            return;
        }

        if (!this.status || !this.status.__progress) {
            this.status = document.createElement("progress");
            this.status.__progress = true;
        }

        this.status.value = progress || 0;
    }

    _updateTestGroupDisabled()
    {
        this.status.checked = !this.representedObject.disabled;

        if (this.representedObject instanceof WI.AuditTestGroup) {
            let firstSupportedTest = this.representedObject.tests.find((test) => test.supported);
            this.status.indeterminate = this.representedObject.tests.some((test) => test.supported && test.disabled !== firstSupportedTest.disabled);
        }
    }

    _handleTestCaseCompleted(event)
    {
        this.representedObject.removeEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCaseCompleted, this);

        this._updateStatus();
    }

    _handleTestDisabledChanged(event)
    {
        if (this.status instanceof HTMLInputElement && this.status.type === "checkbox")
            this._updateTestGroupDisabled();
    }

    _handleTestResultChanged(event)
    {
        this._updateStatus();
    }

    _handleTestCaseScheduled(event)
    {
        this.representedObject.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCaseCompleted, this);

        this._showRunningSpinner();
    }

    _handleTestGroupCompleted(event)
    {
        this.representedObject.removeEventListener(WI.AuditTestBase.Event.Completed, this._handleTestGroupCompleted, this);
        this.representedObject.removeEventListener(WI.AuditTestBase.Event.Progress, this._handleTestGroupProgress, this);

        this._updateStatus();
    }

    _handleTestGroupProgress(event)
    {
        let {index, count} = event.data;
        this._showRunningProgress((index + 1) / count);
    }

    _handleTestGroupScheduled(event)
    {
        this.representedObject.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestGroupCompleted, this);
        this.representedObject.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestGroupProgress, this);

        this._showRunningProgress();
    }

    _handleTestNameChanged(event)
    {
        this.mainTitle = this.representedObject.name;

        if (this.representedObject instanceof WI.AuditTestGroup)
            this._expandedSetting = new WI.Setting(WI.AuditTreeElement.expandedSettingKey(this.representedObject.name), !!WI.Setting.migrateValue(WI.AuditTreeElement.expandedSettingKey(event.data.oldName)));
    }

    _handleTestSupportedChanged(event)
    {
        this._updateStatus();
    }

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

        this.appendChild(new WI.AuditTreeElement(test));
    }

    _handleManagerEditingChanged(event)
    {
        this._updateStatus();
    }

    _handleAuditManagerTestScheduled(event)
    {
        this.addClassName("manager-active");
    }

    _handleAuditManagerTestCompleted(event)
    {
        this.removeClassName("manager-active");
    }

    _handleStatusClick(event)
    {
        this._start();
    }
};
