import { EventEmitter } from "events";
import { merge, find, isEqual } from "lodash-es";
import initializeDefaults from "./defaults";
import PersistentConfig from "./PersistentConfig";
import { default as Tab } from "./Tab";
import * as shareLink from "./linkUtils";
import TabElements from "./TabElements";
import { default as Yasqe } from "@matdata/yasqe";
import { default as Yasr } from "@matdata/yasr";
import { addClass, removeClass } from "@matdata/yasgui-utils";
import GeoPlugin from "yasgui-geo-tg";
import GraphPlugin from "@matdata/yasgui-graph-plugin";
import TablePlugin from "@matdata/yasgui-table-plugin";
import "@matdata/yasgui-graph-plugin/dist/yasgui-graph-plugin.min.css";
import "@matdata/yasgui-table-plugin/dist/yasgui-table-plugin.min.css";
import { ThemeManager } from "./ThemeManager";
import QueryBrowser from "./queryManagement/QueryBrowser";
import "./index.scss";
import "./themes.scss";
import "../../yasr/src/scss/global.scss";
import "codemirror/theme/material-palenight.css";
Yasr.registerPlugin("Table", TablePlugin);
Yasr.registerPlugin("Geo", GeoPlugin);
Yasr.registerPlugin("Graph", GraphPlugin);
if (window) {
    if (Yasqe)
        window.Yasqe = Yasqe;
    if (Yasr)
        window.Yasr = Yasr;
}
export class Yasgui extends EventEmitter {
    constructor(parent, config) {
        super();
        this._tabs = {};
        this.rootEl = document.createElement("div");
        addClass(this.rootEl, "yasgui");
        parent.appendChild(this.rootEl);
        this.config = merge({}, Yasgui.defaults, config);
        this.themeManager = new ThemeManager(this.rootEl);
        if (this.config.theme) {
            this.themeManager.setTheme(this.config.theme);
        }
        this.themeManager.listenToSystemTheme();
        this.persistentConfig = new PersistentConfig(this);
        const persistedShowSnippetsBar = this.persistentConfig.getShowSnippetsBar();
        if (persistedShowSnippetsBar !== undefined) {
            this.config.showSnippetsBar = persistedShowSnippetsBar;
        }
        this.tabElements = new TabElements(this);
        this.tabPanelsEl = document.createElement("div");
        this.queryBrowser = new QueryBrowser(this);
        this.rootEl.appendChild(this.tabElements.drawTabsList());
        this.rootEl.appendChild(this.tabPanelsEl);
        this.rootEl.appendChild(this.queryBrowser.getElement());
        let executeIdAfterInit;
        let optionsFromUrl;
        if (this.config.populateFromUrl) {
            optionsFromUrl = shareLink.getConfigFromUrl(Tab.getDefaults(this));
            if (optionsFromUrl) {
                const tabId = this.findTabIdForConfig(optionsFromUrl);
                if (tabId) {
                    const persistentYasr = this.persistentConfig.getTab(tabId).yasr;
                    this.persistentConfig.getTab(tabId).yasr = {
                        settings: optionsFromUrl.yasr.settings,
                        response: persistentYasr.response,
                    };
                    this.persistentConfig.setActive(tabId);
                    if (!persistentYasr.response) {
                        executeIdAfterInit = tabId;
                    }
                }
                else {
                    this.persistentConfig.setTab(optionsFromUrl.id, typeof this.config.populateFromUrl === "function"
                        ? this.config.populateFromUrl(optionsFromUrl)
                        : optionsFromUrl);
                    executeIdAfterInit = optionsFromUrl.id;
                }
            }
        }
        const tabs = this.persistentConfig.getTabs();
        if (!tabs.length && this.config.autoAddOnInit) {
            const newTab = this.addTab(true);
            this.persistentConfig.setActive(newTab.getId());
            this.emit("tabChange", this, newTab);
        }
        else {
            for (const tabId of tabs) {
                this._tabs[tabId] = new Tab(this, this.persistentConfig.getTab(tabId));
                this._registerTabListeners(this._tabs[tabId]);
                this.tabElements.drawTab(tabId);
            }
            const activeTabId = this.persistentConfig.getActiveId();
            if (activeTabId) {
                this.markTabSelected(activeTabId);
                if (executeIdAfterInit && executeIdAfterInit === activeTabId) {
                    this.getTab(activeTabId).query().catch(() => { });
                }
            }
        }
    }
    hasFullscreen(fullscreen) {
        if (fullscreen) {
            this.emit("fullscreen-enter", this);
            addClass(this.rootEl, "hasFullscreen");
        }
        else {
            this.emit("fullscreen-leave", this);
            removeClass(this.rootEl, "hasFullscreen");
        }
    }
    getStorageId(label, getter) {
        const persistenceId = getter || this.config.persistenceId;
        if (!persistenceId)
            return undefined;
        if (typeof persistenceId === "string")
            return persistenceId + "_" + label;
        return persistenceId(this) + "_" + label;
    }
    createTabName(name, i = 0) {
        if (!name)
            name = this.config.tabName;
        var fullName = name + (i > 0 ? " " + i : "");
        if (this.tabNameTaken(fullName))
            fullName = this.createTabName(name, i + 1);
        return fullName;
    }
    tabNameTaken(name) {
        return find(this._tabs, (tab) => tab.getName() === name);
    }
    getTab(tabId) {
        if (tabId) {
            return this._tabs[tabId];
        }
        const currentTabId = this.persistentConfig.currentId();
        if (currentTabId)
            return this._tabs[currentTabId];
    }
    markTabSelected(tabId) {
        if (!this.persistentConfig.getTab(tabId)) {
            return false;
        }
        this.tabElements.selectTab(tabId);
        if (!this._tabs[tabId]) {
            this._tabs[tabId] = new Tab(this, Tab.getDefaults(this));
        }
        this._tabs[tabId].show();
        for (const otherTabId in this._tabs) {
            if (otherTabId !== tabId)
                this._tabs[otherTabId].hide();
        }
        return true;
    }
    selectTabId(tabId) {
        const tab = this.getTab();
        if (tab && tab.getId() !== tabId) {
            if (this.markTabSelected(tabId)) {
                this.emit("tabSelect", this, tabId);
                this.persistentConfig.setActive(tabId);
            }
        }
        return tab;
    }
    tabConfigEquals(tab1, tab2) {
        var _a, _b, _c, _d;
        let sameRequest = true;
        let key;
        for (key in tab1.requestConfig) {
            if (!tab1.requestConfig[key])
                continue;
            if (!isEqual(tab2.requestConfig[key], tab1.requestConfig[key])) {
                sameRequest = false;
            }
        }
        if (sameRequest) {
            sameRequest = ["endpoint", "value"].every((key) => tab1.yasqe[key] === tab2.yasqe[key]);
        }
        if (sameRequest) {
            sameRequest =
                tab1.yasr.settings.selectedPlugin === tab2.yasr.settings.selectedPlugin &&
                    isEqual((_a = tab1.yasr.settings.pluginsConfig) === null || _a === void 0 ? void 0 : _a[((_b = tab1.yasr.settings) === null || _b === void 0 ? void 0 : _b.selectedPlugin) || ""], (_c = tab2.yasr.settings.pluginsConfig) === null || _c === void 0 ? void 0 : _c[((_d = tab2.yasr.settings) === null || _d === void 0 ? void 0 : _d.selectedPlugin) || ""]);
        }
        return sameRequest && tab1.name === tab2.name;
    }
    findTabIdForConfig(tabConfig) {
        return this.persistentConfig.getTabs().find((tabId) => {
            const tab = this.persistentConfig.getTab(tabId);
            return this.tabConfigEquals(tab, tabConfig);
        });
    }
    _registerTabListeners(tab) {
        tab.on("change", (tab) => this.emit("tabChange", this, tab));
        tab.on("query", (tab) => this.emit("query", this, tab));
        tab.on("queryBefore", (tab) => this.emit("queryBefore", this, tab));
        tab.on("queryAbort", (tab) => this.emit("queryAbort", this, tab));
        tab.on("queryResponse", (tab) => this.emit("queryResponse", this, tab));
        tab.on("autocompletionShown", (tab, widget) => this.emit("autocompletionShown", this, tab, widget));
        tab.on("autocompletionClose", (tab) => this.emit("autocompletionClose", this, tab));
    }
    _setPanel(panelId, panel) {
        for (const id in this._tabs) {
            if (id !== panelId)
                this._tabs[id].hide();
        }
        this.tabPanelsEl.appendChild(panel);
    }
    _removePanel(panel) {
        if (panel)
            this.tabPanelsEl.removeChild(panel);
    }
    addTab(setActive, partialTabConfig, opts = {}) {
        var _a;
        const tabConfig = merge({}, Tab.getDefaults(this), partialTabConfig);
        if (tabConfig.id && this.getTab(tabConfig.id)) {
            throw new Error("Duplicate tab ID");
        }
        if (this.config.copyEndpointOnNewTab && !((_a = partialTabConfig === null || partialTabConfig === void 0 ? void 0 : partialTabConfig.requestConfig) === null || _a === void 0 ? void 0 : _a.endpoint)) {
            const currentTab = this.getTab();
            if (currentTab) {
                tabConfig.requestConfig.endpoint = currentTab.getEndpoint();
            }
        }
        if (opts.avoidDuplicateTabs) {
            const foundTabId = this.findTabIdForConfig(tabConfig);
            if (foundTabId) {
                return this.selectTabId(foundTabId);
            }
        }
        const tabId = tabConfig.id;
        const index = opts.atIndex;
        this.persistentConfig.addToTabList(tabId, index);
        this.emit("tabAdd", this, tabId);
        this._tabs[tabId] = new Tab(this, tabConfig);
        this.emit("tabChange", this, this._tabs[tabId]);
        this.tabElements.addTab(tabId, index);
        this._registerTabListeners(this._tabs[tabId]);
        if (setActive) {
            this.persistentConfig.setActive(tabId);
            this._tabs[tabId].show();
        }
        return this._tabs[tabId];
    }
    restoreLastTab() {
        const config = this.persistentConfig.retrieveLastClosedTab();
        if (config) {
            this.addTab(true, config.tab, { atIndex: config.index });
        }
    }
    getTheme() {
        return this.themeManager.getTheme();
    }
    setTheme(theme) {
        this.themeManager.setTheme(theme);
    }
    toggleTheme() {
        return this.themeManager.toggleTheme();
    }
    destroy() {
        this.removeAllListeners();
        this.tabElements.destroy();
        for (const tabId in this._tabs) {
            const tab = this._tabs[tabId];
            tab.destroy();
        }
        this._tabs = {};
        while (this.rootEl.firstChild)
            this.rootEl.firstChild.remove();
    }
}
Yasgui.Tab = Tab;
Yasgui.linkUtils = shareLink;
Yasgui.Yasr = Yasr;
Yasgui.Yasqe = Yasqe;
Yasgui.defaults = initializeDefaults();
export function getRandomId() {
    return Math.random().toString(36).substring(7);
}
export * from "./queryManagement";
export default Yasgui;
//# sourceMappingURL=index.js.map