/* lib/browser/content/context - A collection of event handlers associated with the right click context menu. */ import browser from "../utilities/browser.js";
import file_browser from "./file_browser.js";
import modal_configuration from "../utilities/modal_configurations.js";
import network from "../utilities/network.js";
import share from "./share.js";
import util from "../utilities/util.js";
// cspell:words agenttype
/**
 * Creates and populates the right click context menu for the file navigate modal types.
 * ```typescript
 * interface module_context {
 *     clipboard: string;                          // Stores a file copy state pending a paste or cut action.
 *     content: (event:MouseEvent) => HTMLElement; // Creates the HTML content of the context menu.
 *     element: HTMLElement;                       // Stores a reference to the element.target associated with a given menu item.
 *     events: {
 *         contextMenuRemove: () => void;            // Removes the file system context menu from the DOM
 *         copy             : (event:Event) => void; // Handler for the *Copy* menu button, which stores file system address information in the application's clipboard.
 *         destroy          : (event:Event) => void; // Handler for the *Destroy* menu button, which is responsible for deleting file system artifacts.
 *         fsNew            : (event:Event) => void; // Handler for the *New Directory* and *New File* menu buttons.
 *         menu             : (event:Event) => void; // Generates the context menu which populates with different menu items depending upon event.target of the right click.
 *         paste            : (event:Event) => void; // Handler for the *Paste* menu item which performs the file copy operation over the network.
 *     };
 *     type: contextType; // Stores a context action type for awareness to the context action event handler.
 * }
 * type contextType = "" | "Base64" | "copy" | "cut" | "directory" | "Edit" | "file" | "Hash";
 * ``` */ const context = {
    clipboard: "",
    content: function browser_content_context_content(event) {
        const element = function browser_content_context_menu_element() {
            const target = event.target, name = target.lowName();
            if (name === "li" || name === "ul") {
                return target;
            }
            return target.getAncestor("li", "tag");
        }(), inputAddress = element.getAncestor("border", "class").getElementsByTagName("input")[0].value, root = inputAddress === "/" || inputAddress === "\\", nodeName = element.lowName(), itemList = [], menu = document.createElement("ul"), command = navigator.userAgent.indexOf("Mac OS X") > 0 ? "Command" : "CTRL", functions = {
            base64: function browser_content_context_menu_base64() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + B`);
                button.appendText("Base64 ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = modal_configuration.modals["file-edit"];
                item.appendChild(button);
                itemList.push(item);
            },
            copy: function browser_content_context_menu_copy() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + C`);
                button.appendText("Copy ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = context.events.copy;
                item.appendChild(button);
                itemList.push(item);
            },
            cut: function browser_content_context_menu_cut() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + X`);
                button.appendText("Cut ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = context.events.copy;
                item.appendChild(button);
                itemList.push(item);
            },
            destroy: function browser_content_context_menu_destroy() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText("DEL");
                button.appendText("Destroy ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.setAttribute("class", "destroy");
                if (root === true) {
                    button.disabled = true;
                } else {
                    button.onclick = context.events.destroy;
                }
                item.appendChild(button);
                itemList.push(item);
            },
            details: function browser_content_context_menu_details() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + T`);
                button.appendText("Details ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = modal_configuration.modals.details;
                item.appendChild(button);
                itemList.push(item);
            },
            edit: function browser_content_context_menu_edit() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + E`);
                if (readOnly === true) {
                    button.appendText("Read File as Text ");
                } else {
                    button.appendText("Edit File as Text ");
                }
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = modal_configuration.modals["file-edit"];
                item.appendChild(button);
                itemList.push(item);
            },
            hash: function browser_content_context_menu_hash() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + H`);
                button.appendText("Hash ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = modal_configuration.modals["file-edit"];
                item.appendChild(button);
                itemList.push(item);
            },
            newDirectory: function browser_content_context_menu_newDirectory() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + D`);
                button.appendText("New Directory ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = context.events.fsNew;
                item.appendChild(button);
                itemList.push(item);
            },
            newFile: function browser_content_context_menu_newFile() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + F`);
                button.appendText("New File ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = context.events.fsNew;
                item.appendChild(button);
                itemList.push(item);
            },
            paste: function browser_content_context_menu_paste() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + V`);
                button.appendText("Paste ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = context.events.paste;
                if (context.clipboard === "" || context.clipboard.indexOf("\"type\":") < 0 || context.clipboard.indexOf("\"data\":") < 0) {
                    button.disabled = true;
                }
                item.appendChild(button);
                itemList.push(item);
            },
            rename: function browser_content_context_menu_rename() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + R`);
                button.appendText("Rename ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                if (root === true) {
                    button.disabled = true;
                } else {
                    button.onclick = file_browser.events.rename;
                }
                item.appendChild(button);
                itemList.push(item);
            },
            share: function browser_content_context_menu_share() {
                const item = document.createElement("li"), button = document.createElement("button"), em = document.createElement("em");
                em.appendText(`${command} + ALT + S`);
                button.appendText("Share ");
                button.appendChild(em);
                button.setAttribute("type", "button");
                button.onclick = share.events.context;
                item.appendChild(button);
                itemList.push(item);
            }
        }, box = element.getAncestor("box", "class"), agentType = box.dataset === undefined ? null : box.dataset.agenttype, readOnly = browser.ui.modals[box.getAttribute("id")].read_only && agentType !== "device", clientHeight = browser.content.clientHeight;
        let clientX, clientY, menuTop = null, reverse = false, a = 0;
        context.element = element;
        context.events.contextMenuRemove();
        event.preventDefault();
        event.stopPropagation();
        menu.setAttribute("id", "contextMenu");
        menu.onclick = context.events.contextMenuRemove;
        if (nodeName === "ul") {
            functions.details();
            if (agentType === "device" || readOnly === false) {
                functions.newDirectory();
                functions.newFile();
                functions.paste();
            }
        } else if (nodeName === "li") {
            functions.details();
            if (agentType === "device") {
                functions.share();
            }
            if (element.getAttribute("class").indexOf("file") === 0) {
                functions.edit();
                functions.hash();
                functions.base64();
            }
            if (readOnly === false) {
                functions.newDirectory();
                functions.newFile();
            }
            functions.copy();
            if (readOnly === false) {
                functions.cut();
                functions.paste();
                functions.rename();
                functions.destroy();
            }
        }
        // this accounts for events artificially created during test automation
        if (event.clientY === undefined || event.clientX === undefined) {
            const body = element.getAncestor("body", "class");
            clientX = element.offsetLeft + body.offsetLeft + box.offsetLeft + 50;
            clientY = element.offsetTop + body.offsetTop + box.offsetTop + 65;
        } else {
            clientX = event.clientX;
            clientY = event.clientY;
        }
        // menu display position
        menu.style.zIndex = `${browser.ui.zIndex + 10}`;
        menuTop = itemList.length * 52 + 1 + clientY;
        // vertical
        if (clientHeight < menuTop) {
            // above cursor
            menu.style.bottom = "1em";
            if (clientY > clientHeight - 52) {
                reverse = true;
            }
        } else {
            // below cursor
            menu.style.top = `${clientY / 10}em`;
        }
        // horizontal
        if (browser.content.clientWidth < 200 + clientX) {
            // right of cursor
            menu.style.left = `${(clientX - 200) / 10}em`;
        } else {
            // left of cursor
            menu.style.left = `${(clientX + 10) / 10}em`;
        }
        // button order
        if (reverse === true) {
            a = itemList.length;
            do {
                a = a - 1;
                menu.appendChild(itemList[a]);
            }while (a > 0)
        } else {
            do {
                menu.appendChild(itemList[a]);
                a = a + 1;
            }while (a < itemList.length)
        }
        return menu;
    },
    /* Stores an element for reference between event and menu action */ element: null,
    events: {
        /* Removes the file system context menu from the DOM */ contextMenuRemove: function browser_content_context_contextMenuRemove() {
            const menu = document.getElementById("contextMenu");
            if (menu !== null) {
                menu.parentNode.removeChild(menu);
            }
        },
        /* Handler for file system artifact copy */ copy: function browser_content_context_copy(event) {
            const addresses = [], tagName = context.element.lowName(), element = tagName === "li" || tagName === "ul" ? context.element : context.element.getAncestor("li", "tag"), menu = document.getElementById("contextMenu"), box = element.getAncestor("box", "class"), contextElement = event.target, type = context.type !== "" ? context.type : contextElement.innerHTML.indexOf("Copy") === 0 ? "copy" : "cut", selected = file_browser.tools.selectedAddresses(element, type), agency = util.getAgent(box), id = box.getAttribute("id"), clipData = {
                agent: agency[0],
                agentType: agency[2],
                data: addresses,
                id: id,
                share: browser.ui.modals[id].share,
                type: type
            }, clipStore = context.clipboard === "" ? null : JSON.parse(context.clipboard);
            if (selected.length < 1) {
                addresses.push(element.getElementsByTagName("label")[0].innerHTML.replace(/&amp;/g, "&"));
            } else {
                selected.forEach(function browser_content_context_destroy_each(value) {
                    addresses.push(value[0].replace(/&amp;/g, "&"));
                });
            }
            if (clipStore !== null) {
                if (clipStore.id !== box.getAttribute("id") || type !== "cut") {
                    file_browser.tools.selectNone(document.getElementById(clipStore.id));
                }
            }
            context.clipboard = JSON.stringify(clipData);
            context.element = null;
            context.type = "";
            if (menu !== null) {
                menu.parentNode.removeChild(menu);
            }
        },
        /* Handler for removing file system artifacts via context menu */ destroy: function browser_content_context_destroy() {
            const element = context.element.lowName() === "li" ? context.element : context.element.getAncestor("li", "tag"), box = element.getAncestor("box", "class"), menu = document.getElementById("contextMenu"), agents = util.fileAgent(box, null), payload = {
                action: "fs-destroy",
                agentRequest: agents[0],
                agentSource: agents[1],
                agentWrite: null,
                depth: 1,
                location: [],
                name: box.getElementsByClassName("header")[0].getElementsByTagName("input")[0].value
            }, selected = file_browser.tools.selectedAddresses(element, "destroy");
            if (selected.length < 1) {
                payload.location.push(element.dataset.path);
            } else {
                selected.forEach(function browser_content_context_destroy_each(value) {
                    payload.location.push(value[0]);
                });
            }
            network.send(payload, "file-system");
            context.element = null;
            if (menu !== null) {
                menu.parentNode.removeChild(menu);
            }
        },
        /* Handler for creating new directories */ fsNew: function browser_content_context_fsNew(event) {
            const element = event.target, menu = document.getElementById("contextMenu"), cancel = function browser_content_context_fsNew_cancel(actionElement) {
                const list = actionElement.getAncestor("fileList", "class"), input = list.getElementsByTagName("input")[0];
                setTimeout(function browser_content_context_fsNew_cancel_delay() {
                    if (actionElement.parentNode.parentNode.parentNode.parentNode === list) {
                        list.removeChild(actionElement.parentNode.parentNode.parentNode);
                        input.focus();
                    }
                }, 10);
            }, actionKeyboard = function browser_content_context_fsNew_actionKeyboard(actionEvent) {
                const actionElement = actionEvent.target, actionParent = actionElement.parentNode;
                if (actionEvent.key === "Enter") {
                    const value = actionElement.value.replace(/(\s+|\.)$/, ""), agents = util.fileAgent(actionParent, null), payload = {
                        action: "fs-new",
                        agentRequest: agents[0],
                        agentSource: agents[1],
                        agentWrite: null,
                        depth: 1,
                        location: [
                            actionElement.dataset.location + value
                        ],
                        name: actionElement.dataset.type
                    };
                    if (value.replace(/\s+/, "") !== "") {
                        actionElement.onkeyup = null;
                        actionElement.onblur = null;
                        actionParent.appendText(payload.location[0], true);
                        network.send(payload, "file-system");
                    }
                } else {
                    if (actionEvent.key === "Escape") {
                        cancel(actionElement);
                        return;
                    }
                    actionElement.value = actionElement.value.replace(/\?|<|>|"|\||\*|:|\\|\/|\u0000/g, "");
                }
            }, actionBlur = function browser_content_context_fsNew_actionBlur(actionEvent) {
                const actionElement = actionEvent.target, value = actionElement.value.replace(/(\s+|\.)$/, "");
                if (actionEvent.type === "blur") {
                    if (value.replace(/\s+/, "") === "") {
                        cancel(actionElement);
                    } else {
                        const actionParent = actionElement.parentNode, agents = util.fileAgent(actionParent, null), payload = {
                            action: "fs-new",
                            agentRequest: agents[0],
                            agentSource: agents[1],
                            agentWrite: null,
                            depth: 1,
                            location: [
                                actionElement.dataset.location + value
                            ],
                            name: actionElement.dataset.type
                        };
                        actionElement.onkeyup = null;
                        actionElement.onblur = null;
                        actionParent.appendText(payload.location[0], true);
                        network.send(payload, "file-system");
                    }
                }
            }, build = function browser_content_context_fsNew_build() {
                const li = document.createElement("li"), label = document.createElement("label"), input = document.createElement("input"), field = document.createElement("input"), text = document.createElement("label"), p = document.createElement("p"), spanInfo = document.createElement("span"), parent = context.element === null ? null : context.element.parentNode, box = parent === null ? null : parent.getAncestor("box", "class"), type = context.type !== "" ? context.type : element.innerHTML.indexOf("New File") === 0 ? "file" : "directory", span = document.createElement("span");
                if (parent === null) {
                    return;
                }
                let slash = "/", path = box.getElementsByTagName("input")[0].value;
                li.setAttribute("class", type);
                if (type === "directory") {
                    li.ondblclick = file_browser.events.directory;
                }
                path = box.getElementsByTagName("input")[0].value;
                if (path.indexOf("/") < 0 || path.indexOf("\\") < path.indexOf("/") && path.indexOf("\\") > -1 && path.indexOf("/") > -1) {
                    slash = "\\";
                }
                if (path.charAt(path.length - 1) !== slash) {
                    path = path + slash;
                }
                input.type = "checkbox";
                input.checked = false;
                label.appendText("Selected");
                label.appendChild(input);
                label.setAttribute("class", "selection");
                p.appendChild(text);
                spanInfo.appendText(type === "file" ? "file - 0 bytes" : "directory - 0 items");
                p.appendChild(spanInfo);
                text.oncontextmenu = context.events.menu;
                text.onclick = file_browser.events.select;
                text.appendText(path);
                field.onkeyup = actionKeyboard;
                field.onblur = actionBlur;
                field.setAttribute("id", "newFileItem");
                field.setAttribute("data-type", type);
                field.setAttribute("data-location", path);
                text.appendChild(field);
                li.appendChild(p);
                span.onclick = file_browser.events.select;
                span.oncontextmenu = context.events.menu;
                li.appendChild(span);
                li.oncontextmenu = context.events.menu;
                li.appendChild(label);
                li.onclick = file_browser.events.select;
                if (context.element.lowName() === "ul") {
                    context.element.appendChild(li);
                } else {
                    context.element.parentNode.appendChild(li);
                }
                field.focus();
            };
            if (document.getElementById("newFileItem") !== null) {
                return;
            }
            build();
            context.element = null;
            context.type = "";
            if (menu !== null) {
                menu.parentNode.removeChild(menu);
            }
        },
        /* Creates context menu */ menu: function browser_content_context_menu(event) {
            browser.content.parentNode.appendChild(context.content(event));
        },
        /* Prepare the network action to write files */ paste: function browser_content_context_paste() {
            const box = context.element.getAncestor("box", "class"), clipData = context.clipboard === "" ? null : JSON.parse(context.clipboard), sourceModal = document.getElementById(clipData.id), menu = document.getElementById("contextMenu"), cut = clipData.type === "cut", agents = util.fileAgent(sourceModal, box), payload = {
                agentRequest: agents[0],
                agentSource: agents[1],
                agentWrite: agents[2],
                cut: cut,
                execute: false,
                location: clipData.data
            };
            if (context.clipboard === "" || box === document.documentElement) {
                return;
            }
            network.send(payload, "copy");
            context.clipboard = "";
            file_browser.tools.selectNone(document.getElementById(clipData.id));
            context.element = null;
            if (menu !== null) {
                menu.parentNode.removeChild(menu);
            }
        }
    },
    /* Stores a context action type for awareness to the context action event handler */ type: ""
};
export default context;
