/** @odoo-module */

import { Component, useState, xml } from "@odoo/owl";
import { refresh, subscribeToURLParams } from "../core/url";
import { STORAGE, storageSet } from "../hoot_utils";
import { HootLink } from "./hoot_link";

/**
 * @typedef {{
 * }} HootButtonsProps
 */

//-----------------------------------------------------------------------------
// Global
//-----------------------------------------------------------------------------

const {
    clearTimeout,
    Object: { keys: $keys },
    setTimeout,
} = globalThis;

//-----------------------------------------------------------------------------
// Internal
//-----------------------------------------------------------------------------

const DISABLE_TIMEOUT = 500;

//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------

/** @extends {Component<HootButtonsProps, import("../hoot").Environment>} */
export class HootButtons extends Component {
    static components = { HootLink };

    static props = {};

    static template = xml`
        <t t-set="isRunning" t-value="runnerState.status === 'running'" />
        <t t-set="showAll" t-value="env.runner.hasFilter" />
        <t t-set="showFailed" t-value="runnerState.failedIds.size" />
        <t t-set="failedSuites" t-value="getFailedSuiteIds()" />
        <div
            class="${HootButtons.name} relative"
            t-on-mouseenter="() => !isRunning and (state.open = true)"
            t-on-mouseleave="() => state.open = false"
        >
            <div class="flex rounded gap-px overflow-hidden">
            <button
                type="button"
                class="flex items-center bg-btn gap-2 px-2 py-1 transition-colors"
                t-on-click.stop="onRunClick"
                t-att-title="isRunning ? 'Stop (Esc)' : 'Run'"
                t-att-disabled="state.disable"
            >
                <i t-attf-class="fa fa-{{ isRunning ? 'stop' : 'play' }}" />
                <span t-esc="isRunning ? 'Stop' : 'Run'" />
            </button>
            <t t-if="showAll or showFailed">
                <button
                    type="button"
                    class="bg-btn px-2 py-1 transition-colors animate-slide-left"
                    t-on-click.stop="() => state.open = !state.open"
                >
                    <i class="fa fa-caret-down transition" t-att-class="{ 'rotate-180': state.open }" />
                </button>
            </t>
            </div>
            <t t-if="state.open">
                <div
                    class="animate-slide-down w-fit absolute flex flex-col end-0 shadow rounded overflow-hidden shadow z-2"
                >
                    <t t-if="showAll">
                        <HootLink class="'bg-btn p-2 whitespace-nowrap transition-colors'">
                            Run <strong>all</strong> tests
                        </HootLink>
                    </t>
                    <t t-if="showFailed">
                        <HootLink
                            type="'test'"
                            id="runnerState.failedIds"
                            class="'bg-btn p-2 whitespace-nowrap transition-colors'"
                            title="'Run failed tests'"
                            onClick="onRunFailedClick"
                        >
                            Run failed <strong>tests</strong>
                        </HootLink>
                        <HootLink
                            type="'suite'"
                            id="failedSuites"
                            class="'bg-btn p-2 whitespace-nowrap transition-colors'"
                            title="'Run failed suites'"
                            onClick="onRunFailedClick"
                        >
                            Run failed <strong>suites</strong>
                        </HootLink>
                    </t>
                </div>
            </t>
        </div>
    `;

    setup() {
        const { runner } = this.env;
        this.state = useState({
            disable: false,
            open: false,
        });
        this.runnerState = useState(runner.state);
        this.disableTimeout = 0;

        subscribeToURLParams(...$keys(runner.config));
    }

    getFailedSuiteIds() {
        const { tests } = this.env.runner;
        const suiteIds = [];
        for (const id of this.runnerState.failedIds) {
            const test = tests.get(id);
            if (test && !suiteIds.includes(test.parent.id)) {
                suiteIds.push(test.parent.id);
            }
        }
        return suiteIds;
    }

    onRunClick() {
        const { runner } = this.env;
        switch (runner.state.status) {
            case "done": {
                refresh();
                break;
            }
            case "ready": {
                if (runner.config.manual) {
                    runner.manualStart();
                } else {
                    refresh();
                }
                break;
            }
            case "running": {
                runner.stop();
                if (this.disableTimeout) {
                    clearTimeout(this.disableTimeout);
                }
                this.state.disable = true;
                this.disableTimeout = setTimeout(
                    () => (this.state.disable = false),
                    DISABLE_TIMEOUT
                );
                break;
            }
        }
    }

    onRunFailedClick() {
        storageSet(STORAGE.failed, []);
    }
}