/* eslint-disable @typescript-eslint/no-unused-vars */
/**
 * Important note: These classes make use of "getters". Don't confuse these with function calls.
 */
import { Startup } from "../clients/Startup/Startup";
import { Logger } from "../clients/logger";
import { RouterClient } from "../clients/routerClient";
/**
 * Flag to control whether API usage tracking is enabled.
 * Defaults to false and should be enabled by FSBLDesktop.
 */
let enableAPITracking = false;
/**
 * Set to track which API channels have already been transmitted
 */
const trackedChannels = new Set();
/**
 * Helper function to conditionally track API usage.
 * Ensures each channel is only transmitted once per session.
 */
function trackAPIUsage(channel) {
    if (!enableAPITracking) {
        return;
    }
    // Skip if already tracked
    if (trackedChannels.has(channel)) {
        return;
    }
    // Mark as tracked and transmit
    trackedChannels.add(channel);
    RouterClient.transmit("logger.service.trackAPIUsage", { channel });
}
class SystemWindow {
    static createNew(params, cb) {
        fin.desktop.Window.createNew(params, cb);
    }
    static getCurrent() {
        return fin.desktop.Window.getCurrent();
    }
    static wrap(windowName) {
        // cache the window wrap object and return it for multiple requests
        if (!this.wrapCache[windowName]) {
            const wrap = fin.desktop.Window.wrap(windowName);
            const closedHandler = () => {
                delete this.wrapCache[windowName];
                wrap.removeEventListener("closed", closedHandler);
            };
            wrap.addEventListener("closed", closedHandler);
            this.wrapCache[windowName] = wrap;
        }
        return this.wrapCache[windowName];
    }
}
SystemWindow.wrapCache = {};
/**
 * Partially emulates a fin SystemWindow when running in a browser.
 */
class FreestandingWindow {
    static createNew(params, cb) {
        cb("Cannot create freestanding windows");
    }
    /**
     * Partial polyfill of FEA's getCurrent() for when running in a freestanding window.
     *
     * A few pieces of core code still rely on `getCurrent().name` (expecting it to be the current windowName).
     *
     * This polyfill can be eliminated when all of those code instances are converted to using getStartupData().
     */
    static getCurrent() {
        // Polyfill calls to getCurrent().name. APIs have expected this to be the windowName.
        const { windowName } = Startup.getInstance().getStartupData();
        return {
            name: windowName,
            uuid: `${windowName}-uuid`,
            // Dummy getOptions that still executes the callback but with empty data (to keep logger.ts going)
            getOptions: (cb) => {
                cb === null || cb === void 0 ? void 0 : cb({});
            },
            addEventListener: () => { },
            removeEventListener: () => { },
            updateOptions: () => { },
            close: () => { },
            startMovingWindow: () => { },
            stopMovingWindow: () => { },
            isShowing: () => { },
            bringToFront: () => { },
            show: () => { },
            hide: () => { },
            setTaskbarIcon: () => { },
        };
    }
    static wrap() {
        return this.getCurrent();
    }
}
/**
 * <h2>Clipboard</h2>
 * @param {object} params
 */
class Clipboard {
    constructor() {
        return new fin.desktop.System.Clipboard();
    }
    /**
     * Write Text to Clipboard
     */
    static writeText(data, type, callback, errorCallback) {
        Logger.deprecated("FSBL.System.Clipboard.writeText is deprecated");
        return fin.desktop.System.Clipboard.writeText(data, type, callback, errorCallback);
    }
    static writeHTML(data, type, callback, errorCallback) {
        Logger.deprecated("FSBL.System.Clipboard.writeHTML is deprecated");
        return fin.desktop.System.Clipboard.writeHTML(data, type, callback, errorCallback);
    }
    static writeRTF(data, type, callback, errorCallback) {
        Logger.deprecated("FSBL.System.Clipboard.writeRTF is deprecated");
        return fin.desktop.System.Clipboard.writeRTF(data, type, callback, errorCallback);
    }
    static readText(type, callback, errorCallback) {
        Logger.deprecated("FSBL.System.Clipboard.readText is deprecated");
        return fin.desktop.System.Clipboard.readText(type, callback, errorCallback);
    }
    static readHTML(type, callback, errorCallback) {
        Logger.deprecated("FSBL.System.Clipboard.readHTML is deprecated");
        return fin.desktop.System.Clipboard.readHTML(type, callback, errorCallback);
    }
    static readRTF(type, callback, errorCallback) {
        Logger.deprecated("FSBL.System.Clipboard.readRTF is deprecated");
        return fin.desktop.System.Clipboard.readRTF(type, callback, errorCallback);
    }
}
/**
 * <h2>The Finsemble System API </h2>
 * ----------
 * The Finsemble System API is a set private and experimental of APIs for exposing operating system and electron-based functionality, including the clipboard, mouse position, monitor info, and others.
 * @private
 */
export class System {
    /**
     * Enables API usage tracking. Should be called by FSBLDesktop.
     */
    static enableAPIUsageTracking() {
        enableAPITracking = true;
    }
    /**
     * Application is deprecated. getCurrent().restart() continues to be used by LTS seed so this must
     * stay until we can remove SDD permanently from seed.
     *
     * The other functions can be removed once clients are confirmed not to be using them.
     */
    static get Application() {
        return {
            getCurrent: () => {
                Logger.deprecated("FSBL.System.Application is deprecated");
                return {
                    restart: () => {
                        trackAPIUsage("FSBL.System.restart");
                        RouterClient.transmit("Application.restart", {});
                    },
                    getWindow: () => fin.desktop.Window,
                    addEventListener: (type, listener, callback, errorCallback) => {
                        trackAPIUsage(`FSBL.System.getCurrent.addEventListener.${type}`);
                        fin.desktop.Window.addEventListener(type, listener, callback, errorCallback);
                    },
                    close: (force, callback, errorCallback) => {
                        fin.desktop.Window.close(force, callback, errorCallback);
                    },
                    getChildWindows: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback([fin.desktop.Window]);
                    },
                    getGroups: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback([]);
                    },
                    getManifest: (callback, errorCallback) => {
                        System.getManifest(callback);
                    },
                    getParentUuid: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback("Finsemble");
                    },
                    getInfo: (callback, errorCallback) => {
                        System.getVersion(callback);
                    },
                    getTrayIconInfo: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback({});
                    },
                    isRunning: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback(true);
                    },
                    registerUser: (userName, appName, callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback();
                    },
                    removeEventListener: (type, previouslyRegisteredListener, callback, errorCallback) => {
                        fin.desktop.Window.removeEventListener(type, previouslyRegisteredListener, callback, errorCallback);
                    },
                    removeTrayIcon: (callback, errorCallback) => {
                        fin.desktop.Window.removeTrayIcon(callback, errorCallback);
                    },
                    run: (callback, errorCallback) => { },
                    scheduleRestart: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback();
                    },
                    setTrayIcon: (iconUrl, listener, callback, errorCallback) => {
                        trackAPIUsage("FSBL.System.setTrayIcon");
                        fin.desktop.Window.setTrayIcon(iconUrl, listener, callback, errorCallback);
                    },
                    terminate: (callback, errorCallback) => {
                        trackAPIUsage("FSBL.System.terminate");
                        System.terminate();
                    },
                    wait: (callback, errorCallback) => {
                        callback === null || callback === void 0 ? void 0 : callback();
                    },
                    window: {
                        name: fin.desktop.Window.name,
                    },
                    uuid: "Finsemble",
                };
            },
        };
    }
    /**
     * Determines if the current window was launched through finsemble, or is external or freestanding
     * @private
     * @returns boolean True if freestanding
     */
    static isFreestanding() {
        return typeof fin === "undefined";
    }
    /**
     * Window
     * @private
     * @returns Window
     */
    static get Window() {
        return System.isFreestanding() ? FreestandingWindow : SystemWindow;
    }
    /**
     * Notification
     * @private
     * @returns Notification
     */
    static get Notification() {
        return {
            send: (params) => {
                trackAPIUsage("FSBL.System.Notification.send");
                fin.desktop.Notification.send(params);
            },
        };
    }
    /**
     * Clipboard
     * @private
     * @returns Clipboard
     */
    static get Clipboard() {
        return Clipboard;
    }
    static getManifest(cb) {
        trackAPIUsage("FSBL.System.getManifest");
        return new Promise((resolve) => {
            fin.desktop.System.getManifest((manifest) => {
                cb === null || cb === void 0 ? void 0 : cb(manifest);
                resolve(manifest);
            });
        });
    }
    /**
     * (experimental) Gets current mouse position
     * @experimental
     * @param cb
     */
    static async getMousePosition(cb) {
        trackAPIUsage("FSBL.System.getMousePosition");
        return new Promise((resolve, reject) => {
            fin.desktop.System.getMousePosition((mousePosition) => {
                if (mousePosition.left || mousePosition.left === 0)
                    mousePosition.x = mousePosition.left;
                if (mousePosition.top || mousePosition.top === 0)
                    mousePosition.y = mousePosition.top;
                cb === null || cb === void 0 ? void 0 : cb(null, mousePosition);
                resolve(mousePosition);
            }, (err) => {
                cb === null || cb === void 0 ? void 0 : cb(err);
                reject(err);
            });
        });
    }
    /**
     * Deletes assets downloaded via the manifest's `appAssets` config
     * @param alias - If set then delete that specific asset, otherwise delete them all
     * @returns A golang style promise that resolves after the delete is complete
     */
    static async deleteAssets(alias) {
        trackAPIUsage("FSBL.System.deleteAssets");
        return await fin.desktop.System.deleteAssets(alias);
    }
    /**
     * Asynchronous method that passes the SmartDesktopDesigner's Server Information to the provided callback
     * @private
     * @returns Clipboard
     */
    static getSDServerInfo(cb = Function.prototype) {
        trackAPIUsage("FSBL.System.getSDServerInfo");
        return new Promise((resolve) => {
            fin.desktop.System.getSDServerInfo((info) => {
                resolve(info);
                cb(info);
            });
        });
    }
    /**
     * Get all monitors
     * @private
     * @param cb Callback with monitorInfo type
     */
    static getMonitorInfo(cb) {
        trackAPIUsage("FSBL.System.getMonitorInfo");
        return new Promise((resolve) => {
            fin.desktop.System.getMonitorInfo((info) => {
                resolve(info);
                if (cb)
                    cb(info);
            });
        });
    }
    /**
     * Returns a boolean that is true when the webcontents are running within an electron browserView
     * @private
     * @returns boolean
     */
    static isBrowserView() {
        return System.isFreestanding() ? false : fin.isBrowserView();
    }
    /**
     * Returns the BrowserViewId.  See  isBrowserView method.
     * @private
     * @returns number The browserViewId
     * @deprecated use getWebContentsId
     */
    static getViewId() {
        Logger.deprecated("FSBL.system.getViewId() is deprecated. Use FSBL.system.getWebContentsId()");
        return fin.getWebContentsId();
    }
    /**
     * Returns the Electron WebContents ID for the current WebContents (view or window)
     * @private
     * @returns number The WebContents ID
     */
    static getWebContentsId() {
        return fin.getWebContentsId();
    }
    /**
     * Does the current webcontents contain browserviews
     * @deprecated - use isTitlebarWindow() instead
     * @private
     * @returns boolean True when the current webcontents are a browserwindow that contains associated browserviews
     */
    static hasBrowserView() {
        Logger.deprecated("FSBL.system.hasBrowserView() is deprecated. Use FSBL.system.isTitlebarWindow()");
        return System.isTitlebarWindow();
    }
    /**
     * Is the current webcontents a title bar shell
     * @private
     * @returns boolean True when the current webcontents is a title bar shell
     */
    static isTitlebarWindow() {
        return System.isFreestanding() ? false : fin.isTitlebarWindow();
    }
    /**
     * Returns the fin object
     * @private
     * @returns fin
     */
    static get fin() {
        return fin || {};
    }
    /**
     * Invokes optional callback and resolves promise when FEA is ready.
     *
     * @param {Function} [cb] Optional callback for system ready
     * @private
     * @returns Promise<void>
     * @deprecated It is no longer necessary to wait on ready
     */
    static ready(cb) {
        return new Promise((resolve) => {
            fin.desktop.main(() => {
                if (cb)
                    cb();
                resolve();
            });
        });
    }
    /**
     * Sets the icon for the system tray
     * @param url The url of the icon to use in the system tray
     */
    static setTrayIcon(url, cb) {
        trackAPIUsage("FSBL.System.setTrayIcon");
        fin.desktop.System.setTrayIcon(url, cb);
    }
    /**
     * Asynchronous method that passes the host specs of the system to the provided callback
     * @private
     * @param cb callback
     */
    static getHostSpecs(cb = Function.prototype) {
        trackAPIUsage("FSBL.System.getHostSpecs");
        return new Promise((resolve) => {
            fin.desktop.System.getHostSpecs((info) => {
                resolve(info);
                cb(info);
            });
        });
    }
    /**
     * Returns the InterApplicationBus
     * @private
     * @returns IAB
     */
    static get InterApplicationBus() {
        return fin.desktop.InterApplicationBus;
    }
    /**
     * Launches an external application
     * @private
     */
    static get launchExternalProcess() {
        trackAPIUsage("FSBL.System.launchExternalProcess");
        return fin.desktop.System.launchExternalProcess;
    }
    /**
     * Terminates an external application
     * @private
     */
    static get terminateExternalProcess() {
        trackAPIUsage("FSBL.System.terminateExternalProcess");
        return fin.desktop.System.terminateExternalProcess;
    }
    /**
     * Hard terminates Finsemble.
     *
     * (deprecated) Use `FSBL.shutdownApplication()`
     * @private
     */
    static get exit() {
        return fin.desktop.System.exit;
    }
    /**
     * Clears finsemble cache
     * @private
     */
    static async clearCache(options) {
        trackAPIUsage("FSBL.System.clearCache");
        return fin.desktop.System.clearCache(options);
    }
    /**
     * Shows the chromium developer tools for the current window
     * @private
     * @returns IAB
     */
    static get showDeveloperTools() {
        trackAPIUsage("FSBL.System.showDeveloperTools");
        return fin.desktop.System.showDeveloperTools;
    }
    /**
     * Returns runtime information
     * @private
     * @returns RunTimeInfo
     */
    /**
     * Adds an event listener
     * @private
     * @returns RunTimeInfo
     */
    static get addEventListener() {
        trackAPIUsage("FSBL.System.addEventListener");
        /**
         * Events that Finsemble listen's for: monitor-info-changed and session-changed.
         * When running in freestanding mode (browser) we listen on window.addEventListener
         * though these events are not supported
         */
        return System.isFreestanding() ? window.addEventListener : fin.desktop.System.addEventListener;
    }
    static get removeEventListener() {
        trackAPIUsage("FSBL.System.removeEventListener");
        return System.isFreestanding() ? window.removeEventListener : fin.desktop.System.removeEventListener;
    }
    static get addSelectClientCertificateListener() {
        trackAPIUsage("FSBL.System.addSelectClientCertificateListener");
        return fin.desktop.System.addSelectClientCertificateListener;
    }
    static get addCertificateErrorListener() {
        trackAPIUsage("FSBL.System.addCertificateErrorListener");
        return fin.desktop.System.addCertificateErrorListener;
    }
    static getFEAInfo(cb) {
        trackAPIUsage("FSBL.System.getFEAInfo");
        return new Promise((resolve) => {
            fin.desktop.System.getFEAInfo((info) => {
                cb === null || cb === void 0 ? void 0 : cb(info);
                resolve(info);
            });
        });
    }
    /**
     * getVersion
     * @private
     * @deprecated Use getFEAInfo instead.
     * @returns getVersion function
     */
    static get getVersion() {
        trackAPIUsage("FSBL.System.getVersion");
        return fin.desktop.System.getVersion;
    }
    /**
     * getUpdateAvailable
     * @private
     * @returns getUpdateAvailable function
     */
    static get getUpdateAvailable() {
        trackAPIUsage("FSBL.System.getUpdateAvailable");
        return fin.desktop.System.getUpdateAvailable;
    }
    /**
     * (deprecated) Opens website with external browser
     * @returns openUrlWithBrowser function
     */
    static get openUrlWithBrowser() {
        trackAPIUsage("FSBL.System.openUrlWithBrowser");
        return fin.desktop.System.openUrlWithBrowser;
    }
    /**
     * getProcessList
     * @private
     * @returns getProcessList function
     */
    static get getProcessList() {
        trackAPIUsage("FSBL.System.getProcessList");
        return fin.desktop.System.getProcessList;
    }
    /**
     * getProtocolString
     * @private
     * @returns getProtocolString function
     */
    static get getProtocolString() {
        trackAPIUsage("FSBL.System.getProtocolString");
        return fin.desktop.System.getProtocolString;
    }
    /**
     * hideSplashScreen
     * @private
     * @returns hideSplashScreen function
     */
    static get hideSplashScreen() {
        trackAPIUsage("FSBL.System.hideSplashScreen");
        return fin.desktop.System.hideSplashScreen;
    }
    /**
     * notifyLoggerReady
     * @private
     */
    static notifyLoggerReady() {
        trackAPIUsage("FSBL.System.notifyLoggerReady");
        fin.desktop.System.notifyLoggerReady();
    }
    /**
     * updateCentralLoggerState
     * @private
     */
    static updateCentralLoggerState(loggerState) {
        trackAPIUsage("FSBL.System.updateCentralLoggerState");
        fin.desktop.System.updateCentralLoggerState(loggerState);
    }
    /**
     * Performs handshake with FEA to indicate the primary application started successfully
     * @private
     */
    static startupApplicationHandshake() {
        if (fin.desktop.System.startupApplicationHandshake) {
            fin.desktop.System.startupApplicationHandshake();
        }
    }
    /**
     * Hard terminates the application.
     * This is called only by Finsemble's ShutdownManager to stop the entire application
     * after it has gracefully closed services. Do not call this directly. Use `FSBL.shutdownApplication()`.
     * @private
     */
    static terminate() {
        fin.desktop.System.terminate();
    }
    /**
     * Hard resets the application.
     * This is called only by Finsemble's ShutdownManager to restart the entire application
     * after it has gracefully closed services. Do not call this directly. Use `FSBL.restartApplication()`.
     * @private
     */
    static restart() {
        fin.desktop.System.restart();
    }
    /**
     * Gets an environment variable by name
     * @param envVar The name of the environment variable to fetch
     * @param cb the optional callback
     * @returns a Promise that resolves to the environment variable value
     * @private
     */
    static getEnvironmentVariable(envVar, cb) {
        trackAPIUsage("FSBL.System.getEnvironmentVariable");
        return new Promise((resolve) => {
            fin.desktop.System.getEnvironmentVariable(envVar, (variable) => {
                cb === null || cb === void 0 ? void 0 : cb(variable);
                resolve(variable);
            });
        });
    }
}
//# sourceMappingURL=system.js.map