
/* lib/browser/content/global_events - Events not associated with specific content or a modal type. */

import agent_management from "./agent_management.js";
import browser from "../utilities/browser.js";
import common from "../../common/common.js";
import file_browser from "./file_browser.js";
import modal from "../utilities/modal.js";
import network from "../utilities/network.js";
import share from "./share.js";
import util from "../utilities/util.js";

/**
 * Provides a common location to store events associated with the application at large opposed to content or utility specific events.
 * ```typescript
 * interface module_globalEvents {
 *     contextMenuRemove: () => void;            // Removes a context menu if one is visible.
 *     fullscreen       : (event:Event) => void; // An event handler that launches the browser into fullscreen mode.
 *     fullscreenChange : (event:Event) => void; // An event handler that executes when the browser moves in or out of fullscreen mode.
 *     menu             : (event:Event) => void; // Displays the primary modal in the top left corner of the application.
 *     menuBlur         : (event:Event) => void; // Destroys the menu, if present.
 *     minimizeAll      : (event:Event) => void; // Forcefully minimizes all modals to the tray at the bottom of the application.
 *     minimizeAllFlag  : boolean;               // A flag that halts state saving until all modals are minimized.
 *     modal: {
 *         agentManagement: (event:MouseEvent, config?:config_modal) => void; // Displays agent management modal content from the main menu.
 *         configuration  : (event:MouseEvent) => void;                       // Displays a configuration modal from the main menu.
 *         export         : (event:MouseEvent) => void;                       // Displays an Import/Export modal from the main menu.
 *         fileNavigate   : (Event:Event, config?: navConfig) => void;        // Displays a File Navigate modal from the main menu.
 *         textPad        : (event:Event, config?:config_modal) => Element;   // Displays a TextPad modal from the main menu.
 *     };
 *     shareAll: (event:MouseEvent) => void; // Displays a Share modal associated with multiple agents.
 * }
 * ``` */
const global_events:module_globalEvents = {
    contextMenuRemove: function browser_content_global_contextMenuRemove():void {
        const menu:Element = document.getElementById("contextMenu");
        if (menu !== null) {
            menu.parentNode.removeChild(menu);
        }
    },
    fullscreen: function browser_content_global_fullscreen():void {
        if (document.fullscreenEnabled === true) {
            if (document.fullscreenElement === null) {
                browser.pageBody.requestFullscreen();
            } else {
                document.exitFullscreen();
            }
        }
    },
    fullscreenChange: function browser_content_global_fullscreenChange():void {
        const button:HTMLElement = document.getElementById("fullscreen"),
            span:Element = button.getElementsByTagName("span")[0];
        let text:string = (document.fullscreenElement === null)
            ? "Toggle Fullscreen"
            : "Exit Fullscreen";
        span.innerHTML = text;
        button.title = text;
        button.firstChild.textContent = (document.fullscreenElement === null)
            ? "\u26f6"
            : "\u26cb";
    },

    /* Show/hide for the primary application menu that hangs off the title bar. */
    menu: function browser_content_global_menu():void {
        const menu:HTMLElement = document.getElementById("menu"),
            move = function browser_content_global_menu_move(event:MouseEvent):void {
                if (event.clientX > menu.clientWidth || event.clientY > menu.clientHeight + 51) {
                    menu.style.display = "none";
                    document.onmousemove = null;
                }
            };
        if (menu.style.display !== "block") {
            menu.style.display = "block";
        } else {
            menu.style.display = "none";
        }
        document.onmousemove = move;
    },

    /* Hides the primary menu on blur. */
    menuBlur: function browser_content_global_menuBlur():void {
        const active:Element = document.activeElement,
            menu:HTMLElement = document.getElementById("menu");
        if (active.parentNode.parentNode !== menu) {
            menu.style.display = "none";
        }
    },

    /* Minimize all modals to the bottom tray that are of modal status: normal and maximized */
    minimizeAll: function browser_content_global_minimizeAll():void {
        const keys:string[] = Object.keys(browser.data.modals),
            length:number = keys.length;
        let a:number = 0,
            status:modalStatus;
        global_events.minimizeAllFlag = true;
        do {
            status = browser.data.modals[keys[a]].status;
            if (status === "normal" || status === "maximized") {
                modal.tools.forceMinimize(keys[a]);
            }
            a = a + 1;
        } while (a < length);
        global_events.minimizeAllFlag = false;
        network.configuration();
    },

    /* A flag to keep settings informed about application state in response to minimizing all modals. */
    minimizeAllFlag: false,

    modal: {
        /* Create an agent management modal */
        agentManagement: function browser_content_global_agentManagement(event:MouseEvent, config?:config_modal):void {
            if (config === undefined) {
                const content:Element = agent_management.content.menu("invite"),
                    payloadModal:config_modal = {
                        agent: browser.data.hashDevice,
                        agentIdentity: false,
                        agentType: "device",
                        content: content,
                        inputs: ["cancel", "close", "confirm", "maximize", "minimize"],
                        read_only: false,
                        single: true,
                        title: "<span class=\"icon-delete\">❤</span> Manage Agents",
                        type: "agent-management",
                        width: 750
                    };
                modal.content(payloadModal);
                network.configuration();
            } else {
                config.agent = browser.data.hashDevice;
                config.agentIdentity = false;
                config.content = agent_management.content.menu("invite");
                config.single = true;
                config.title = "<span class=\"icon-delete\">❤</span> Manage Agents";
                config.type = "agent-management";
                modal.content(config);
            }
        },

        /* Open the configuration modal */
        configuration: function browser_content_global_configuration(event:MouseEvent):void {
            const configuration:HTMLElement = document.getElementById("configuration-modal"),
                data:config_modal = browser.data.modals["configuration-modal"];
            modal.events.zTop(event, configuration);
            if (data.status === "hidden") {
                configuration.style.display = "block";
            }
            data.status = "normal";
            document.getElementById("menu").style.display = "none";
        },

        /* Creates an import/export modal */
        export: function browser_content_global_export(event:MouseEvent):void {
            const element:Element = event.target as Element,
                textArea:HTMLTextAreaElement = document.createElement("textarea"),
                label:Element = document.createElement("label"),
                span:Element = document.createElement("span"),
                agency:agency = (element === document.getElementById("export"))
                    ? [browser.data.hashDevice, false, "device"]
                    : util.getAgent(element),
                payload:config_modal = {
                    agent: agency[0],
                    agentIdentity: false,
                    agentType: "device",
                    content: label,
                    inputs: ["cancel", "close", "confirm", "maximize", "minimize"],
                    read_only: agency[1],
                    single: true,
                    title: element.innerHTML,
                    type: "export"
                };
            textArea.onblur = modal.events.textSave;
            textArea.value = JSON.stringify(browser.data);
            span.innerHTML = "Import/Export Settings";
            label.appendChild(span);
            label.appendChild(textArea);
            label.setAttribute("class", "textPad");
            modal.content(payload);
            document.getElementById("menu").style.display = "none";
        },

        /* Create a file navigate modal */
        fileNavigate: function browser_content_global_fileNavigate(event:Event, config?:config_fileNavigate):void {
            const agentName:string = (config === undefined || config.agentName === undefined)
                    ? browser.data.hashDevice
                    : config.agentName,
                agentType:agentType = (agentName === browser.data.hashDevice)
                    ? "device"
                    : config.agentType,
                location:string = (config !== undefined && typeof config.path === "string")
                    ? config.path
                    : "**root**",
                share:string = (config === undefined || config.share === undefined)
                    ? ""
                    : config.share,
                readOnly:boolean = (agentName !== browser.data.hashDevice && config !== undefined && config.readOnly === true),
                readOnlyString:string = (readOnly === true && agentType === "user")
                    ? "(Read Only) "
                    : "",
                // agents not abstracted in order to make use of a config object for state restoration
                payloadNetwork:service_fileSystem = {
                    action: "fs-directory",
                    agentRequest: {
                        device: browser.data.hashDevice,
                        modalAddress: "",
                        share: "",
                        user: browser.data.hashUser
                    },
                    agentSource: {
                        device: (agentType === "device")
                            ? agentName
                            : "",
                        modalAddress: location,
                        share: share,
                        user: (agentType === "device")
                            ? browser.data.hashUser
                            : agentName
                    },
                    agentWrite: null,
                    depth: 2,
                    location: [location],
                    name: "navigate"
                },
                payloadModal:config_modal = {
                    agent: agentName,
                    agentIdentity: true,
                    agentType: agentType,
                    content: util.delay(),
                    inputs: ["close", "maximize", "minimize", "text"],
                    read_only: readOnly,
                    selection: {},
                    share: share,
                    status_bar: true,
                    text_event: file_browser.events.text,
                    text_placeholder: "Optionally type a file system address here.",
                    text_value: location,
                    title: `${document.getElementById("fileNavigator").innerHTML} ${readOnlyString}`,
                    type: "fileNavigate",
                    width: 800
                };
            network.send(payloadNetwork, "file-system");
            modal.content(payloadModal);
            document.getElementById("menu").style.display = "none";
        },

        /* Creates a textPad modal */
        textPad: function browser_content_global_textPad(event:Event, config?:config_modal):Element {
            const element:Element = (event === null)
                    ? null
                    : event.target as Element,
                titleText:string = (element === null)
                    ? ""
                    : element.innerHTML,
                textArea:HTMLTextAreaElement = document.createElement("textarea"),
                label:Element = document.createElement("label"),
                span:Element = document.createElement("span"),
                agency:agency = (element === document.getElementById("textPad"))
                    ? [browser.data.hashDevice, false, "device"]
                    : (element === null)
                        ? null
                        : util.getAgent(element),
                payload:config_modal = (config === undefined)
                    ? {
                        agent: agency[0],
                        agentIdentity: false,
                        agentType: agency[2],
                        content: label,
                        id: (config === undefined)
                            ? null
                            : config.id,
                        inputs: ["close", "maximize", "minimize"],
                        read_only: agency[1],
                        title: titleText,
                        type: "textPad",
                        width: 800
                    }
                    : config;
            let box:Element;
            span.innerHTML = "Text Pad";
            label.setAttribute("class", "textPad");
            label.appendChild(span);
            label.appendChild(textArea);
            if (config !== undefined) {
                textArea.value = config.text_value;
                payload.content = label;
            }
            textArea.onblur = modal.events.textSave;
            if (titleText.indexOf("Base64 - ") === 0) {
                textArea.style.whiteSpace = "normal";
            }
            box = modal.content(payload);
            box.getElementsByClassName("body")[0].getElementsByTagName("textarea")[0].onkeyup = modal.events.textTimer;
            document.getElementById("menu").style.display = "none";
            return box;
        }
    },

    /* Associates share content to share modals representing multiple agents. */
    shareAll: function browser_content_global_shareAll(event:MouseEvent):void {
        const element:Element = event.target as Element,
            parent:Element = element.parentNode as Element,
            classy:string = element.getAttribute("class");
        if (parent.getAttribute("class") === "all-shares") {
            share.tools.modal("", "", null);
        } else if (classy === "device-all-shares") {
            share.tools.modal("", "device", null);
        } else if (classy === "user-all-shares") {
            share.tools.modal("", "user", null);
        }
    }
};

export default global_events;