import TabContextMenu from "./TabContextMenu";
import { hasClass, addClass, removeClass } from "@matdata/yasgui-utils";
import sortablejs from "sortablejs";
import "./TabElements.scss";
export class TabListEl {
    constructor(yasgui, tabList, tabId) {
        this.renameSubmitted = false;
        this.tabList = tabList;
        this.yasgui = yasgui;
        this.tabId = tabId;
    }
    delete() {
        var _a;
        if (this.tabEl) {
            (_a = this.tabList._tabsListEl) === null || _a === void 0 ? void 0 : _a.removeChild(this.tabEl);
            delete this.tabList._tabs[this.tabId];
        }
    }
    startRename() {
        if (this.renameEl) {
            const tab = this.yasgui.getTab(this.tabId);
            if (tab) {
                this.renameSubmitted = false;
                this.renameEl.value = tab.name();
                addClass(this.tabEl, "renaming");
                this.renameEl.focus();
            }
        }
    }
    active(active) {
        if (!this.tabEl)
            return;
        if (active) {
            addClass(this.tabEl, "active");
            this.tabEl.children[0].setAttribute("aria-selected", "true");
            this.tabEl.children[0].setAttribute("tabindex", "0");
        }
        else {
            removeClass(this.tabEl, "active");
            this.tabEl.children[0].setAttribute("aria-selected", "false");
            this.tabEl.children[0].setAttribute("tabindex", "-1");
        }
    }
    rename(name) {
        if (this.nameEl) {
            this.nameEl.textContent = name;
        }
    }
    setAsQuerying(querying) {
        if (querying) {
            addClass(this.tabEl, "querying");
        }
        else {
            removeClass(this.tabEl, "querying");
        }
    }
    setAsRenaming(renaming) {
        if (renaming) {
            addClass(this.tabEl, "renamingInProgress");
            if (this.renameEl)
                this.renameEl.disabled = true;
        }
        else {
            removeClass(this.tabEl, "renamingInProgress");
            if (this.renameEl)
                this.renameEl.disabled = false;
        }
    }
    draw(name) {
        var _a;
        this.tabEl = document.createElement("div");
        this.tabEl.setAttribute("role", "presentation");
        this.tabEl.ondblclick = () => {
            this.startRename();
        };
        addClass(this.tabEl, "tab");
        const tabConf = this.yasgui.persistentConfig.getTab(this.tabId);
        if (tabConf === null || tabConf === void 0 ? void 0 : tabConf.managedQuery) {
            addClass(this.tabEl, "managed");
        }
        const initialTab = this.yasgui.getTab(this.tabId);
        if ((_a = initialTab === null || initialTab === void 0 ? void 0 : initialTab.hasUnsavedManagedChanges) === null || _a === void 0 ? void 0 : _a.call(initialTab)) {
            addClass(this.tabEl, "managedDirty");
        }
        this.tabEl.addEventListener("keydown", (e) => {
            if (!this.tabEl)
                return;
            if (e.code === "Delete" && !this.tabEl.classList.contains("renaming")) {
                handleDeleteTab();
            }
        });
        const handleDeleteTab = (e) => {
            var _a;
            e === null || e === void 0 ? void 0 : e.preventDefault();
            (_a = this.yasgui.getTab(this.tabId)) === null || _a === void 0 ? void 0 : _a.close();
        };
        const tabLinkEl = document.createElement("a");
        tabLinkEl.setAttribute("role", "tab");
        tabLinkEl.href = "#" + this.tabId;
        tabLinkEl.id = "tab-" + this.tabId;
        tabLinkEl.setAttribute("aria-controls", this.tabId);
        tabLinkEl.draggable = false;
        tabLinkEl.addEventListener("blur", () => {
            if (!this.tabEl)
                return;
            if (this.tabEl.classList.contains("active")) {
                tabLinkEl.setAttribute("tabindex", "0");
            }
            else {
                tabLinkEl.setAttribute("tabindex", "-1");
            }
        });
        tabLinkEl.addEventListener("focus", () => {
            if (!this.tabEl)
                return;
            if (this.tabEl.classList.contains("active")) {
                const listEl = this.tabList._tabsListEl;
                if (!listEl)
                    return;
                this.tabList.tabEntryIndex = Array.prototype.indexOf.call(listEl.children, this.tabEl);
            }
        });
        tabLinkEl.addEventListener("click", (e) => {
            e.preventDefault();
            this.yasgui.selectTabId(this.tabId);
        });
        this.nameEl = document.createElement("span");
        this.nameEl.textContent = name;
        tabLinkEl.appendChild(this.nameEl);
        const closeBtn = document.createElement("div");
        closeBtn.innerHTML = "&#x2716;";
        closeBtn.title = "Close tab";
        closeBtn.setAttribute("tabindex", "-1");
        closeBtn.setAttribute("aria-hidden", "true");
        addClass(closeBtn, "closeTab");
        closeBtn.addEventListener("click", handleDeleteTab);
        tabLinkEl.appendChild(closeBtn);
        const renameEl = (this.renameEl = document.createElement("input"));
        renameEl.type = "text";
        renameEl.value = name;
        const submitRename = () => {
            var _a;
            if (this.renameSubmitted)
                return;
            this.renameSubmitted = true;
            void ((_a = this.yasgui.getTab(this.tabId)) === null || _a === void 0 ? void 0 : _a.renameTab(renameEl.value));
            removeClass(this.tabEl, "renaming");
        };
        renameEl.onkeyup = (event) => {
            if (event.key === "Enter") {
                submitRename();
            }
        };
        renameEl.onblur = () => {
            submitRename();
        };
        renameEl.addEventListener("mousedown", (e) => {
            e.stopPropagation();
        });
        renameEl.addEventListener("dragstart", (e) => {
            e.stopPropagation();
        });
        tabLinkEl.appendChild(this.renameEl);
        tabLinkEl.oncontextmenu = (ev) => {
            var _a;
            (_a = this.tabList.tabContextMenu) === null || _a === void 0 ? void 0 : _a.closeConfigMenu();
            this.openTabConfigMenu(ev);
            ev.preventDefault();
            ev.stopPropagation();
        };
        this.tabEl.appendChild(tabLinkEl);
        const loaderEl = document.createElement("div");
        addClass(loaderEl, "loader");
        this.tabEl.appendChild(loaderEl);
        return this.tabEl;
    }
    openTabConfigMenu(event) {
        var _a;
        (_a = this.tabList.tabContextMenu) === null || _a === void 0 ? void 0 : _a.openConfigMenu(this.tabId, this, event);
    }
    redrawContextMenu() {
        var _a;
        (_a = this.tabList.tabContextMenu) === null || _a === void 0 ? void 0 : _a.redraw();
    }
}
export class TabList {
    constructor(yasgui) {
        this._tabs = {};
        this.handleKeydownArrowKeys = (e) => {
            var _a, _b, _c, _d;
            if (e.code === "ArrowLeft" || e.code === "ArrowRight") {
                if (((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.tagName) === "INPUT")
                    return;
                if (!this._tabsListEl)
                    return;
                const numOfChildren = this._tabsListEl.childElementCount;
                if (typeof this.tabEntryIndex !== "number")
                    return;
                const isQueryBrowserToggleEntry = (el) => { var _a, _b; return !!((_b = (_a = el).querySelector) === null || _b === void 0 ? void 0 : _b.call(_a, ".queryBrowserToggle")); };
                const advance = (direction) => {
                    let nextIndex = this.tabEntryIndex;
                    for (let i = 0; i < numOfChildren; i++) {
                        nextIndex += direction;
                        if (nextIndex < 0)
                            nextIndex = numOfChildren - 1;
                        if (nextIndex >= numOfChildren)
                            nextIndex = 0;
                        const candidate = this._tabsListEl.children[nextIndex];
                        if (isQueryBrowserToggleEntry(candidate))
                            continue;
                        if (!candidate.children[0])
                            continue;
                        return nextIndex;
                    }
                    return this.tabEntryIndex;
                };
                const tabEntryDiv = this._tabsListEl.children[this.tabEntryIndex];
                if (!tabEntryDiv.classList.contains("active")) {
                    (_b = tabEntryDiv.children[0]) === null || _b === void 0 ? void 0 : _b.setAttribute("tabindex", "-1");
                }
                if (e.code === "ArrowLeft") {
                    this.tabEntryIndex = advance(-1);
                }
                if (e.code === "ArrowRight") {
                    this.tabEntryIndex = advance(1);
                }
                const newTabEntryDiv = this._tabsListEl.children[this.tabEntryIndex];
                (_c = newTabEntryDiv.children[0]) === null || _c === void 0 ? void 0 : _c.setAttribute("tabindex", "0");
                (_d = newTabEntryDiv.children[0]) === null || _d === void 0 ? void 0 : _d.focus();
            }
        };
        this.handleAddNewTab = (event) => {
            event.preventDefault();
            this.yasgui.addTab(true);
        };
        this.yasgui = yasgui;
        this.registerListeners();
        this.tabEntryIndex = this.getActiveIndex();
    }
    get(tabId) {
        return this._tabs[tabId];
    }
    registerListeners() {
        this.yasgui.on("query", (_yasgui, tab) => {
            const id = tab.getId();
            if (this._tabs[id]) {
                this._tabs[id].setAsQuerying(true);
            }
        });
        this.yasgui.on("queryResponse", (_yasgui, tab) => {
            const id = tab.getId();
            if (this._tabs[id]) {
                this._tabs[id].setAsQuerying(false);
            }
        });
        this.yasgui.on("queryAbort", (_yasgui, tab) => {
            const id = tab.getId();
            if (this._tabs[id]) {
                this._tabs[id].setAsQuerying(false);
            }
        });
        this.yasgui.on("tabChange", (_yasgui, tab) => {
            var _a;
            const id = tab.getId();
            const tabEl = (_a = this._tabs[id]) === null || _a === void 0 ? void 0 : _a.tabEl;
            if (!tabEl)
                return;
            if (tab.isManagedQueryTab()) {
                addClass(tabEl, "managed");
            }
            else {
                removeClass(tabEl, "managed");
            }
            if (tab.hasUnsavedManagedChanges()) {
                addClass(tabEl, "managedDirty");
            }
            else {
                removeClass(tabEl, "managedDirty");
            }
        });
    }
    getActiveIndex() {
        if (!this._selectedTab)
            return;
        const allTabs = Object.keys(this._tabs);
        const currentTabIndex = allTabs.indexOf(this._selectedTab);
        return currentTabIndex;
    }
    drawTabsList() {
        this._tabsListEl = document.createElement("div");
        addClass(this._tabsListEl, "tabsList");
        this._tabsListEl.setAttribute("role", "tablist");
        this._tabsListEl.addEventListener("keydown", this.handleKeydownArrowKeys);
        this._queryBrowserToggleEl = document.createElement("div");
        this._queryBrowserToggleEl.setAttribute("role", "presentation");
        const queryBrowserButton = document.createElement("button");
        queryBrowserButton.type = "button";
        queryBrowserButton.className = "queryBrowserToggle";
        queryBrowserButton.setAttribute("aria-label", "Open query browser");
        queryBrowserButton.title = "Open query browser";
        queryBrowserButton.innerHTML = '<i class="fas fa-bars"></i>';
        queryBrowserButton.addEventListener("click", () => {
            this.yasgui.queryBrowser.toggle(queryBrowserButton);
        });
        this._queryBrowserToggleEl.appendChild(queryBrowserButton);
        this._tabsListEl.appendChild(this._queryBrowserToggleEl);
        sortablejs.create(this._tabsListEl, {
            group: "tabList",
            animation: 100,
            onUpdate: (_ev) => {
                const tabs = this.deriveTabOrderFromEls();
                this.yasgui.emit("tabOrderChanged", this.yasgui, tabs);
                this.yasgui.persistentConfig.setTabOrder(tabs);
            },
            filter: ".queryBrowserToggle, .addTab, input, .renaming",
            preventOnFilter: false,
            onMove: (ev, _origEv) => {
                return hasClass(ev.related, "tab");
            },
        });
        this.addTabEl = document.createElement("div");
        this.addTabEl.setAttribute("role", "presentation");
        const addTabLink = document.createElement("button");
        addTabLink.className = "addTab";
        addTabLink.textContent = "+";
        addTabLink.title = "Add tab";
        addTabLink.setAttribute("aria-label", "Add a new tab");
        addTabLink.addEventListener("click", this.handleAddNewTab);
        addTabLink.addEventListener("focus", () => {
            if (!this._tabsListEl)
                return;
            this.tabEntryIndex = this._tabsListEl.childElementCount - 1;
        });
        addTabLink.addEventListener("blur", () => {
            addTabLink.setAttribute("tabindex", "0");
        });
        this.addTabEl.appendChild(addTabLink);
        this._tabsListEl.appendChild(this.addTabEl);
        this.tabContextMenu = TabContextMenu.get(this.yasgui, this.yasgui.config.contextMenuContainer ? this.yasgui.config.contextMenuContainer : this._tabsListEl);
        return this._tabsListEl;
    }
    addTab(tabId, index) {
        return this.drawTab(tabId, index);
    }
    deriveTabOrderFromEls() {
        const tabs = [];
        if (this._tabsListEl) {
            for (let i = 0; i < this._tabsListEl.children.length; i++) {
                const child = this._tabsListEl.children[i];
                const anchorTag = child.children[0];
                if (anchorTag) {
                    const href = anchorTag.href;
                    if (href && href.indexOf("#") >= 0) {
                        tabs.push(href.substr(href.indexOf("#") + 1));
                    }
                }
            }
        }
        return tabs;
    }
    selectTab(tabId) {
        this._selectedTab = tabId;
        for (const id in this._tabs) {
            this._tabs[id].active(this._selectedTab === id);
        }
    }
    drawTab(tabId, index) {
        var _a, _b;
        this._tabs[tabId] = new TabListEl(this.yasgui, this, tabId);
        const tabConf = this.yasgui.persistentConfig.getTab(tabId);
        if (index !== undefined && index < this.yasgui.persistentConfig.getTabs().length - 1) {
            (_a = this._tabsListEl) === null || _a === void 0 ? void 0 : _a.insertBefore(this._tabs[tabId].draw(tabConf.name), this._tabs[this.yasgui.persistentConfig.getTabs()[index + 1]].tabEl || null);
        }
        else {
            (_b = this._tabsListEl) === null || _b === void 0 ? void 0 : _b.insertBefore(this._tabs[tabId].draw(tabConf.name), this.addTabEl || null);
        }
    }
    destroy() {
        var _a, _b;
        for (const tabId in this._tabs) {
            const tab = this._tabs[tabId];
            tab.delete();
        }
        this._tabs = {};
        (_a = this.tabContextMenu) === null || _a === void 0 ? void 0 : _a.destroy();
        (_b = this._tabsListEl) === null || _b === void 0 ? void 0 : _b.remove();
        this._tabsListEl = undefined;
        this._queryBrowserToggleEl = undefined;
    }
}
export default TabList;
//# sourceMappingURL=TabElements.js.map