/* lib/browser/content/agent_management - Provide control of agent data: delete, invite, and edit. */ import browser from "../utilities/browser.js";
import common from "../../common/common.js";
import configuration from "./configuration.js";
import modal from "../utilities/modal.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
/**
 * Manages agent data in the browser.
 * ```typescript
 * interface module_agentManagement {
 *     content: {
 *         deleteAgents: () => HTMLElement;
 *         inviteRemote: (invitation:service_invite, name:string) => HTMLElement;
 *         inviteStart: () => HTMLElement;
 *         menu: (view:"delete"|"edit_names"|"invite") => HTMLElement;
 *         modifyAgents: () => HTMLElement;
 *     };
 *     events: {
 *         confirm: (event:MouseEvent) => void;
 *         confirmInvite: (event:MouseEvent, options:config_modal) => void;
 *         confirmModify: (event:MouseEvent) => void;
 *         deleteShare: (event:MouseEvent) => void;
 *         deleteToggle: (event:MouseEvent) => void;
 *         displayIP: (event:MouseEvent) => void;
 *         inviteDecline: (event:MouseEvent) => void;
 *         invitePortValidation: (event:Event) => void;
 *         inviteTypeToggle: (event:MouseEvent) => void;
 *         modeToggle: (event:MouseEvent) => void;
 *     };
 *     tools: {
 *         addAgent: (input:agentManagement_addAgent) => void;
 *         confirmDelete: (box:modal) => void;
 *         deleteAgent: (agent:string, agentType:agentType) => void;
 *         inviteAccept: (box:modal) => void;
 *         inviteComplete: (invitation:service_invite, modal:HTMLElement) => void;
 *         inviteReceive: (invitation:service_invite) => void;
 *         inviteTransmissionReceipt: (socketData:socketData) => void;
 *         modifyReceive: (socketData:socketData) => void;
 *     };
 * }
 * ``` */ const agent_management = {
    content: {
        /* Modal content for the agent delete list. */ deleteAgents: function browser_content_agentManagement_deleteAgents() {
            const content = document.createElement("div"), h3 = document.createElement("h3");
            let li, input, label, p, strong, h4, names, length, total = 0, ul = document.createElement("ul");
            content.setAttribute("class", "delete-agents");
            common.agents({
                countBy: "agent",
                perAgent: function browser_content_agentManagement_deleteAgents_perAgent(agentNames) {
                    if (agentNames.agentType !== "device" || agentNames.agentType === "device" && agentNames.agent !== browser.identity.hashDevice) {
                        li = document.createElement("li");
                        li.setAttribute("class", "summary");
                        label = document.createElement("label");
                        input = document.createElement("input");
                        input.type = "checkbox";
                        input.value = agentNames.agent;
                        input.setAttribute("data-type", agentNames.agentType);
                        input.onclick = agent_management.events.deleteToggle;
                        label.appendChild(input);
                        label.appendText(browser.agents[agentNames.agentType][agentNames.agent].name);
                        li.appendChild(label);
                        ul.appendChild(li);
                    }
                },
                perAgentType: function browser_content_agentManagement_deleteAgents_perAgentType(agentNames) {
                    h4 = document.createElement("h4");
                    h4.appendText(`${common.capitalize(agentNames.agentType)}s`);
                    names = Object.keys(browser.agents[agentNames.agentType]);
                    length = names.length;
                    content.appendChild(h4);
                    total = total + length;
                    if (agentNames.agentType === "device" && length < 2 || agentNames.agentType !== "device" && length < 1) {
                        p = document.createElement("p");
                        p.setAttribute("class", "summary");
                        p.appendText(`No ${agentNames.agentType}s to delete.`);
                        content.appendChild(p);
                    } else {
                        ul = document.createElement("ul");
                        content.appendChild(ul);
                    }
                },
                source: browser
            });
            if (total > 1) {
                p = document.createElement("p");
                strong = document.createElement("strong");
                strong.appendText("Please be warned that confirming these change is permanent.");
                p.appendChild(strong);
                p.appendText(" Confirming any selected changes will remove the relationship both locally and on the remote devices/users.");
                content.insertBefore(p, content.firstChild);
                h3.appendText("Delete Agents");
                content.insertBefore(h3, content.firstChild);
            }
            return content;
        },
        /* Modal content for invitation notification on remote agents. */ inviteRemote: function browser_content_agentManagement_inviteRemote(invitation, name) {
            const div = document.createElement("div"), agentInvite = invitation.agentRequest, strong = document.createElement("strong"), angryStrong = document.createElement("strong"), em = document.createElement("em"), ip = agentInvite.ipSelected.indexOf(":") < 0 ? `${agentInvite.ipSelected}:${agentInvite.ports.http}` : `[${agentInvite.ipSelected}]:${agentInvite.ports.http}`, label = document.createElement("label"), textarea = document.createElement("textarea");
            let text = document.createElement("h3");
            div.setAttribute("class", "agentInvitation");
            div.setAttribute("data-agenttype", invitation.type);
            strong.appendText(name);
            text.appendText("User ");
            text.appendChild(strong);
            text.appendText(` from ${ip} is inviting you to share of type `);
            angryStrong.appendText(common.capitalize(invitation.type));
            angryStrong.setAttribute("class", "warning");
            text.appendChild(angryStrong);
            text.appendText(".");
            div.appendChild(text);
            text = document.createElement("p");
            label.appendText(`${name} said:`);
            textarea.value = invitation.message;
            label.appendChild(textarea);
            text.appendChild(label);
            div.appendChild(text);
            text = document.createElement("p");
            em.appendText("Confirm");
            text.appendText("Press the ");
            text.appendChild(em);
            text.appendText(" button to accept the invitation or close this modal to ignore it.");
            div.appendChild(text);
            div.setAttribute("data-invitation", JSON.stringify(invitation));
            return div;
        },
        /* Modal content for the invite agents fields. */ inviteStart: function browser_content_agentManagement_inviteStart() {
            const inviteElement = document.createElement("div"), separator = "|spaces|", blur = function browser_content_agentManagement_inviteStart_blur(focusEvent) {
                const element = focusEvent.target, box = element.getAncestor("box", "class"), id = box.getAttribute("id"), inputs = box.getElementsByTagName("input"), textArea = box.getElementsByTagName("textarea")[0];
                agent_management.events.invitePortValidation(focusEvent);
                browser.ui.modals[id].text_value = inputs[0].value + separator + inputs[1].value + separator + textArea.value;
                network.configuration();
            }, textInput = function browser_content_agentManagement_inviteStart_textInput(labelText) {
                const label = document.createElement("label"), input = labelText === "Invitation Message" ? document.createElement("textarea") : document.createElement("input");
                p = document.createElement("p");
                label.appendText(labelText);
                input.setAttribute("type", "text");
                input.onblur = blur;
                input.setAttribute("class", labelText.indexOf("Message") > 0 ? "message" : labelText.slice(0, labelText.indexOf(" ")).toLowerCase());
                label.appendChild(input);
                p.appendChild(label);
                section.appendChild(p);
            }, ul = document.createElement("ul"), h3 = document.createElement("h3"), name = `invite-type${Math.random()}`;
            let p = document.createElement("p"), h4 = document.createElement("h4"), section = document.createElement("div");
            h3.appendText("Invite An Agent");
            inviteElement.appendChild(h3);
            // Type
            h4.appendText("Connection Type");
            section.appendChild(h4);
            util.radioListItem({
                defaultValue: "User",
                handler: agent_management.events.inviteTypeToggle,
                list: [
                    "User",
                    "Device"
                ],
                name: name,
                parent: ul
            });
            section.appendChild(ul);
            // type description text
            section.setAttribute("class", "section");
            p.setAttribute("class", "type-description");
            p.appendText("Including a user allows sharing with a different person and the devices they make available.");
            section.appendChild(p);
            inviteElement.appendChild(section);
            section = document.createElement("div");
            section.setAttribute("class", "section");
            h4 = document.createElement("h4");
            h4.appendText("Connection Details");
            section.appendChild(h4);
            // IP address
            textInput("IP Address");
            // Port
            textInput("Port (defaults to 443 if blank)");
            // Message
            textInput("Invitation Message");
            inviteElement.appendChild(section);
            inviteElement.setAttribute("class", "inviteAgent");
            return inviteElement;
        },
        /* The radio buttons at the top of the modal content. */ menu: function browser_content_agentManagement_menu(view) {
            const div = document.createElement("div"), ul = document.createElement("ul"), h3 = document.createElement("h3"), name = `agent-management-${Math.random()}`, bodyDelete = agent_management.content.deleteAgents(), bodyInvite = agent_management.content.inviteStart(), bodyModify = agent_management.content.modifyAgents();
            util.radioListItem({
                defaultValue: view,
                handler: agent_management.events.modeToggle,
                list: [
                    "Invite",
                    "Edit Names",
                    "Delete"
                ],
                name: name,
                parent: ul
            });
            ul.setAttribute("class", "section");
            h3.appendText("Select An Action");
            div.appendChild(h3);
            div.appendChild(ul);
            div.appendChild(bodyInvite);
            div.appendChild(bodyModify);
            div.appendChild(bodyDelete);
            if (view === "delete") {
                bodyDelete.style.display = "block";
            } else if (view === "invite") {
                bodyInvite.style.display = "block";
            } else if (view === "edit_names") {
                bodyModify.style.display = "block";
            }
            div.setAttribute("class", "agent-management");
            return div;
        },
        /* Modal content for the modify agents area. */ modifyAgents: function browser_content_agentManagement_modifyAgents() {
            const div = document.createElement("div"), h3 = document.createElement("h3"), // ipSection = function browser_content_agentManagement_modifyAgents_ipSection():HTMLElement {
            //     const container:HTMLElement = document.createElement("div"),
            //         heading:HTMLElement = document.createElement("h4"),
            //         warning:HTMLElement = document.createElement("p"),
            //         strong:HTMLElement = document.createElement("strong"),
            //         list:HTMLElement = document.createElement("ul");
            //     heading.appendText("Display IP Address Information");
            //     util.radioListItem({
            //         defaultValue: "No",
            //         handler: agent_management.events.displayIP,
            //         list: ["No", "Yes"],
            //         name: `agent-ip-display-${Math.random()}`,
            //         parent: list
            //     });
            //     strong.appendText("Manually modifying IP address data may result in an unrecoverable disconnection.");
            //     warning.appendChild(strong);
            //     container.appendChild(heading);
            //     container.appendChild(warning);
            //     container.appendChild(list);
            //     container.setAttribute("class", "section");
            //     return container;
            // },
            section = function browser_content_agentManagement_modifyAgents_section(agentType) {
                const container = document.createElement("div"), heading = document.createElement("h4"), keys = Object.keys(browser.agents[agentType]), len = keys.length, list = len < 1 ? document.createElement("p") : document.createElement("ul"), item = function browser_content_agentManagement_modifyAgents_section_item(key) {
                    let p = document.createElement("p");
                    const label = document.createElement("label"), input = document.createElement("input"), li = document.createElement("li");
                    // agent hash
                    p.appendText(key);
                    p.setAttribute("class", "modify-agent-hash");
                    li.append(p);
                    // agent name
                    p = document.createElement("p");
                    input.type = "text";
                    input.value = browser.agents[agentType][key].name;
                    input.setAttribute("data-agent", key);
                    input.setAttribute("data-type", agentType);
                    label.appendText("Name");
                    label.appendChild(input);
                    p.appendChild(label);
                    li.appendChild(p);
                    // agent IPv6
                    // p = document.createElement("p");
                    // label = document.createElement("label");
                    // textArea.value = browser[agentType][key].ipAll.IPv6.join(",\n");
                    // label.appendText("IPv6 Addresses");
                    // label.appendChild(textArea);
                    // p.appendChild(label);
                    // p.style.display = "none";
                    // p.setAttribute("class", "agent-management-ip");
                    // li.appendChild(p);
                    // agent IPv4
                    // p = document.createElement("p");
                    // label = document.createElement("label");
                    // textArea = document.createElement("textarea");
                    // textArea.value = browser[agentType][key].ipAll.IPv4.join(",\n");
                    // label.appendText("IPv4 Addresses");
                    // label.appendChild(textArea);
                    // p.appendChild(label);
                    // p.style.display = "none";
                    // p.setAttribute("class", "agent-management-ip");
                    // li.appendChild(p);
                    return li;
                };
                heading.appendText(common.capitalize(agentType));
                if (len < 1) {
                    list.appendText(`No agents of type ${agentType}.`);
                } else {
                    let index = 0;
                    do {
                        list.appendChild(item(keys[index]));
                        index = index + 1;
                    }while (index < len)
                    list.setAttribute("class", "modify-agent-list");
                }
                container.appendChild(heading);
                container.appendChild(list);
                div.appendChild(container);
            };
            h3.appendText("Edit Agent Names");
            div.appendChild(h3);
            // div.appendChild(ipSection());
            section("device");
            section("user");
            div.setAttribute("class", "modify-agents");
            return div;
        }
    },
    events: {
        /* Handles the confirmation button for the agent management modal type. */ confirm: function browser_content_agentManagement_confirm(event) {
            const target = event.target, box = target.getAncestor("box", "class"), firstInput = box.getElementsByTagName("input")[0], type = function browser_content_agentManagement_confirm_type() {
                const radios = document.getElementsByName(firstInput.getAttribute("name"));
                let len = radios.length;
                do {
                    len = len - 1;
                    if (radios[len].checked === true) {
                        return radios[len].value;
                    }
                }while (len > 0)
                return null;
            }();
            if (type === "invite") {
                agent_management.events.confirmInvite(event, browser.ui.modals[box.getAttribute("id")]);
            } else if (type === "edit_names") {
                agent_management.events.confirmModify(event);
            } else if (type === "delete") {
                agent_management.tools.confirmDelete(box);
            }
        },
        /* Send the invite request to the network */ confirmInvite: function browser_content_agentManagement_confirmInvite(event, options) {
            let type, ip, port, portNumber;
            const element = event.target, box = element.getAncestor("box", "class"), body = box.getElementsByClassName("body")[0], content = body.getElementsByClassName("inviteAgent")[0], input = function browser_content_agentManagement_confirmInvite_input() {
                // value attainment and form validation
                const inputs = content.getElementsByTagName("input"), length = inputs.length, indexes = {
                    type: -1,
                    ip: -1,
                    port: -1
                };
                let a = 0, parentNode;
                do {
                    parentNode = inputs[a].parentNode;
                    if (inputs[a].value === "device" || inputs[a].value === "user") {
                        if (inputs[a].value === "device") {
                            indexes.type = a;
                        }
                        if (inputs[a].checked === true) {
                            type = inputs[a].value;
                        }
                    } else if (parentNode.innerHTML.indexOf("IP Address") === 0) {
                        indexes.ip = a;
                        ip = inputs[a].value;
                    } else if (parentNode.innerHTML.indexOf("Port") === 0) {
                        indexes.port = a;
                        port = inputs[a].value;
                    }
                    a = a + 1;
                }while (a < length)
                if (type === undefined) {
                    return inputs[indexes.type];
                }
                if (ip === undefined || ip.replace(/\s+/, "") === "" || /(\d{1,3}\.){3}\d{1,3}/.test(ip) === false && /([a-f0-9]{4}:)+/.test(ip) === false) {
                    return inputs[indexes.ip];
                }
                if (port === undefined || port.replace(/^\s+$/, "") === "") {
                    port = "";
                    portNumber = location.href.indexOf("https") === 0 ? 443 : 80;
                } else {
                    portNumber = Number(port);
                    if (isNaN(portNumber) === true || portNumber < 0 || portNumber > 65535) {
                        return inputs[indexes.port];
                    }
                }
                return null;
            }(), saved = {
                ip: ip,
                message: content.getElementsByTagName("textarea")[0].value.replace(/"/g, "\\\""),
                port: port,
                type: type
            }, userData = common.userData(browser.agents.device, type, browser.identity.hashDevice), invitation = {
                action: "invite-start",
                agentRequest: {
                    devices: null,
                    hashUser: "",
                    ipAll: userData[1],
                    ipSelected: "",
                    modal: options.id,
                    nameUser: browser.identity.nameUser,
                    ports: browser.network.ports,
                    secret: "",
                    session: "",
                    shares: userData[0]
                },
                agentSource: {
                    devices: null,
                    hashUser: "",
                    ipAll: null,
                    ipSelected: ip,
                    modal: "",
                    nameUser: "",
                    ports: {
                        http: portNumber,
                        ws: 0
                    },
                    secret: "",
                    session: "",
                    shares: null
                },
                message: saved.message,
                status: "invited",
                type: type
            };
            options.text_value = JSON.stringify(saved);
            network.configuration();
            if (input !== null) {
                const p = input.parentNode.parentNode, warning = document.createElement("p"), strong = document.createElement("strong");
                p.setAttribute("class", "warning");
                input.focus();
                strong.appendText("Please select an invitation type.");
                warning.appendChild(strong);
                warning.setAttribute("class", "inviteWarning");
                p.parentNode.appendChild(warning);
                return;
            }
            content.style.display = "none";
            if (content.getElementsByClassName("error").length > 0) {
                content.removeChild(content.getElementsByClassName("error")[0]);
            }
            body.appendChild(util.delay());
            network.send(invitation, "invite");
        },
        /* Handle confirmation of changes to agent data. */ confirmModify: function browser_content_agentManagement_confirmModify(event) {
            const target = event.target, box = target.getAncestor("box", "class"), boxes = document.getElementsByClassName("box"), modify = box.getElementsByClassName("modify-agents")[0], inputs = modify.getElementsByTagName("input"), flags = {
                device: false,
                user: false
            }, modifyService = {
                action: "rename",
                agents: {
                    device: {},
                    user: {}
                },
                agentFrom: browser.identity.hashDevice,
                identity: null
            }, modifyModals = function browser_content_agentManagement_confirmModify_modifyModals(agent, type, name) {
                const typeString = `${common.capitalize(type)}, `;
                let boxLen = boxes.length, button = null, text = "";
                do {
                    boxLen = boxLen - 1;
                    if (boxes[boxLen].dataset.agent === agent && boxes[boxLen].dataset.agenttype === type) {
                        button = boxes[boxLen].getElementsByTagName("button")[0];
                        text = button.innerHTML;
                        text = text.slice(0, text.indexOf(typeString) + typeString.length) + name;
                        button.appendText(text);
                    }
                }while (boxLen > 0)
            };
            let len = inputs.length, agent = "", name = "", type = null, value = "";
            do {
                len = len - 1;
                agent = inputs[len].dataset.agent;
                type = inputs[len].dataset.type;
                name = browser.agents[type][agent].name;
                value = inputs[len].value;
                if (value !== name) {
                    flags[type] = true;
                    browser.agents[type][agent].name = value;
                    document.getElementById(agent).lastChild.textContent = ` ${value}`;
                    modifyModals(agent, type, value);
                    modifyService.agents[type][agent] = browser.agents[type][agent];
                }
            }while (len > 0)
            if (flags.user === true || flags.device === true) {
                network.send(modifyService, "agent-management");
                network.configuration();
            }
        },
        /* Removes a share from a device of the local user. */ deleteShare: function browser_content_agentManagement_deleteShare(event) {
            const element = event.target, parent = element.parentNode, box = parent.getAncestor("box", "class"), agent = function browser_content_agentManagement_deleteShare_agency() {
                let agentNode = parent;
                do {
                    agentNode = agentNode.parentNode;
                }while (agentNode.getAttribute("class") !== "device" && agentNode.getAttribute("class") !== "user")
                return agentNode.dataset.hash;
            }(), address = parent.getElementsByClassName("read-only-status")[0].previousSibling.textContent, shares = agent === null ? null : browser.agents.device[agent].shares, keys = agent === null ? null : Object.keys(shares), length = agent === null ? 0 : keys.length, manage = {
                action: "modify",
                agentFrom: browser.identity.hashDevice,
                agents: {
                    device: {},
                    user: {}
                },
                identity: null
            };
            let a = 0;
            if (length < 1) {
                return;
            }
            do {
                if (shares[keys[a]].name === address) {
                    delete shares[keys[a]];
                    break;
                }
                a = a + 1;
            }while (a < length)
            if (length === 1) {
                const p = document.createElement("p"), granny = parent.parentNode, em = document.createElement("em");
                em.appendText(browser.agents.device[agent].name);
                p.appendText("Device ");
                p.appendChild(em);
                p.appendText(" has no shares.");
                granny.parentNode.insertBefore(p, granny);
                granny.parentNode.removeChild(granny);
            } else {
                parent.parentNode.removeChild(parent);
            }
            share.tools.update(box.getAttribute("id"));
            manage.agents.device[agent] = browser.agents.device[agent];
            network.send(manage, "agent-management");
        },
        /* Changes visual state of items in the agent delete list as they are checked or unchecked. */ deleteToggle: function browser_content_agentManagement_deleteToggle(event) {
            const element = event.target, label = element.parentNode;
            if (element.checked === true) {
                label.setAttribute("class", "checked");
            } else {
                label.removeAttribute("class");
            }
        },
        /* Shows and hides IP address information from the Modify view of agent management */ displayIP: function browser_content_agentManagement_displayIP(event) {
            const target = event.target, body = target.getAncestor("body", "class"), value = target.value === "yes" ? "block" : "none", ipList = body.getElementsByClassName("agent-management-ip");
            let len = ipList.length;
            if (len > 0) {
                do {
                    len = len - 1;
                    ipList[len].style.display = value;
                }while (len > 0)
            }
        },
        /* Handler for declining an invitation request */ inviteDecline: function browser_content_invite_decline(event) {
            const element = event.target, boxLocal = element.getAncestor("box", "class"), inviteBody = boxLocal.getElementsByClassName("agentInvitation")[0], invitation = JSON.parse(inviteBody.dataset.invitation);
            invitation.action = "invite-answer";
            invitation.status = "declined";
            network.send(invitation, "invite");
            modal.events.close(event);
        },
        /* Basic form validation on the port field */ invitePortValidation: function browser_content_agentManagement_invitePortValidation(event) {
            const portElement = event.target, keyboardEvent = event, portParent = portElement.parentNode, element = portParent.innerHTML.indexOf("Port") === 0 ? portElement : function browser_content_agentManagement_invitePortValidation_findElement() {
                const content = portParent.getAncestor("inviteAgent", "class");
                return content.getElementsByClassName("port")[0];
            }(), value = element.value.replace(/\s+/g, ""), numb = Number(value);
            if (event.type === "blur" || event.type === "keyup" && keyboardEvent.key === "Enter") {
                if (value !== "" && (isNaN(numb) === true || numb < 1 || numb > 65535)) {
                    element.style.color = "#f00";
                    element.style.borderColor = "#f00";
                    element.parentNode.firstChild.textContent = "Error: Port must be a number from 1-65535 or empty.";
                    element.focus();
                } else {
                    element.parentNode.firstChild.textContent = "Port";
                    element.removeAttribute("style");
                }
            }
        },
        /* Switch text messaging in the invitation request modal when the user clicks on the type radio buttons */ inviteTypeToggle: function browser_content_agentManagement_inviteTypeToggle(event) {
            const element = event.target, inviteAgent = element.getAncestor("inviteAgent", "class"), warning = inviteAgent.getElementsByClassName("inviteWarning")[0], description = inviteAgent.getElementsByClassName("type-description")[0], strong = document.createElement("strong");
            if (warning !== undefined) {
                warning.parentNode.removeChild(warning);
            }
            if (element.value === "device") {
                strong.appendText("Including a personal device will provide unrestricted access to and from that device.");
                description.appendText("", true);
                description.appendChild(strong);
                description.appendText(" This username will be imposed upon that device.");
            } else {
                description.appendText("Including a user allows sharing with a different person and the devices they make available.", true);
            }
            description.style.display = "block";
            configuration.tools.radio(element);
        },
        /* Changes the content between invite, delete, edit of agent data */ modeToggle: function browser_content_agentManagement_modeToggle(event) {
            const target = event.target, box = target.getAncestor("box", "class"), body = box.getElementsByClassName("body")[0], bodyDelete = body.getElementsByClassName("delete-agents")[0], bodyInvite = body.getElementsByClassName("inviteAgent")[0], bodyModify = body.getElementsByClassName("modify-agents")[0], footer = box.getElementsByClassName("footer")[0];
            footer.style.display = "block";
            if (target.value === "delete") {
                bodyDelete.style.display = "block";
                bodyInvite.style.display = "none";
                bodyModify.style.display = "none";
            } else if (target.value === "invite") {
                bodyDelete.style.display = "none";
                bodyInvite.style.display = "block";
                bodyModify.style.display = "none";
            } else if (target.value === "edit_names") {
                bodyDelete.style.display = "none";
                bodyInvite.style.display = "none";
                bodyModify.style.display = "block";
            }
        }
    },
    tools: {
        /* Adds an agent into the browser user interface whether the agent is new or the page is loading. */ addAgent: function browser_content_agentManagement_addAgent(input) {
            const li = document.createElement("li"), button = document.createElement("button"), addStyle = function browser_content_agentManagement_addUser_addStyle() {
                let body, heading;
                if (browser.ui.colors[input.type][input.hash] === undefined) {
                    body = configuration.colorDefaults[browser.ui.color][0];
                    heading = configuration.colorDefaults[browser.ui.color][1];
                    browser.ui.colors[input.type][input.hash] = [
                        body,
                        heading
                    ];
                    if (input.callback === undefined) {
                        network.configuration();
                    } else {
                        network.send({
                            settings: browser.ui,
                            type: "ui"
                        }, "settings");
                        input.callback();
                    }
                } else {
                    body = browser.ui.colors[input.type][input.hash][0];
                    heading = browser.ui.colors[input.type][input.hash][1];
                }
                if (browser.loading === false) {
                    configuration.tools.styleText({
                        agent: input.hash,
                        agentType: input.type,
                        colors: [
                            body,
                            heading
                        ],
                        replace: false
                    });
                }
            }, status = function browser_content_agentManagement_addUser_status(status) {
                const em = document.createElement("em"), span = document.createElement("span");
                em.setAttribute("class", `status-${status}`);
                em.appendText("●");
                span.appendText(` ${common.capitalize(status)}`);
                em.appendChild(span);
                return em;
            };
            button.appendChild(status("active"));
            button.appendChild(status("idle"));
            button.appendChild(status("offline"));
            button.appendText(` ${input.name}`);
            if (input.hash === browser.identity.hashDevice) {
                button.setAttribute("class", "active");
            } else {
                button.setAttribute("class", browser.agents[input.type][input.hash].status);
            }
            button.setAttribute("id", input.hash);
            button.setAttribute("data-agenttype", input.type);
            button.setAttribute("type", "button");
            button.onclick = modal_configuration.modals.shares;
            li.appendChild(button);
            document.getElementById(input.type).getElementsByTagName("ul")[0].appendChild(li);
            addStyle();
            configuration.tools.addUserColor(input.hash, input.type);
            if (browser.loading === false) {
                share.tools.update("");
            }
        },
        /* Processes agent termination from a delete-agents content of agent-management */ confirmDelete: function browser_content_agentManagement_confirmDelete(box) {
            const body = box.getElementsByClassName("body")[0], list = body.getElementsByClassName("delete-agents")[0].getElementsByTagName("li"), manage = {
                action: "delete",
                agentFrom: browser.identity.hashDevice,
                agents: {
                    device: {},
                    user: {}
                },
                identity: null
            };
            let a = list.length, count = 0, input, type, subtitle, hash, parent;
            // put the deleted agents into a list
            do {
                a = a - 1;
                input = list[a].getElementsByTagName("input")[0];
                if (input.checked === true) {
                    hash = input.value;
                    type = input.dataset.type;
                    parent = document.getElementById(hash).parentNode;
                    if (list[a].parentNode.childNodes.length < 2) {
                        subtitle = document.createElement("p");
                        subtitle.appendText(`No ${type}s to delete.`);
                        subtitle.setAttribute("class", "summary");
                        list[a].parentNode.parentNode.insertBefore(subtitle, list[a].parentNode);
                        list[a].parentNode.parentNode.removeChild(list[a].parentNode);
                    } else {
                        list[a].parentNode.removeChild(list[a]);
                    }
                    manage.agents[type][hash] = browser.agents[type][hash];
                    parent.parentNode.removeChild(parent);
                    agent_management.tools.deleteAgent(hash, type);
                    count = count + 1;
                }
            }while (a > 0)
            if (count < 1) {
                return;
            }
            network.send(manage, "agent-management");
            share.tools.update("");
            network.configuration();
        },
        /* Removes an agent from the browser interface */ deleteAgent: function browser_content_agentManagement_deleteAgent(agent, agentType) {
            const userColors = document.getElementById("configuration-modal").getElementsByClassName(`${agentType}-color-list`)[0].getElementsByTagName("li"), shareModals = document.getModalsByModalType("shares"), colorLength = userColors.length, button = document.getElementById(agent), parent = button === null ? null : button.parentNode;
            let a = 0, shareLength = shareModals.length, closeButton = null;
            // loop through the color swatches in the settings modal to remove the agent's colors
            if (colorLength > 0) {
                do {
                    if (userColors[a].dataset.agent === agent) {
                        userColors[a].parentNode.removeChild(userColors[a]);
                        configuration.tools.styleText({
                            agent: agent,
                            agentType: agentType,
                            colors: [
                                "",
                                ""
                            ],
                            replace: true
                        });
                        break;
                    }
                    a = a + 1;
                }while (a < colorLength)
            }
            // remove the agent from the data structures
            delete browser.agents[agentType][agent];
            delete browser.ui.colors[agentType][agent];
            // remove agent associated share modals
            if (shareLength > 0) {
                do {
                    shareLength = shareLength - 1;
                    if (shareModals[shareLength].dataset.agent === agent && shareModals[shareLength].dataset.agenttype === agentType) {
                        closeButton = shareModals[shareLength].getElementsByClassName("close")[0];
                        closeButton.click();
                    }
                }while (shareLength > 0)
            }
            // remove the named button for the agent
            if (parent !== null && button.dataset.agenttype === agentType) {
                parent.parentNode.removeChild(parent);
            }
        },
        /* Accept an invitation, handler on a modal's confirm button */ inviteAccept: function browser_content_agentManagement_inviteAccept(box) {
            const div = box.getElementsByClassName("agentInvitation")[0], invitation = JSON.parse(div.dataset.invitation);
            invitation.action = "invite-answer";
            invitation.message = `Invite accepted: ${common.dateFormat(new Date())}`;
            invitation.status = "accepted";
            if (invitation.type === "device") {
                browser.identity.hashUser = invitation.agentRequest.hashUser;
                browser.identity.nameUser = invitation.agentRequest.nameUser;
                network.configuration();
            }
            network.send(invitation, "invite");
        },
        /* Handles final status of an invitation completion */ inviteComplete: function browser_content_agentManagement_inviteComplete(invitation, modal) {
            if (modal !== null) {
                const error = modal.getElementsByClassName("error")[0], delay = modal.getElementsByClassName("delay")[0], footer = modal.getElementsByClassName("footer")[0], inviteAgent = modal.getElementsByClassName("inviteAgent")[0], lastChild = inviteAgent.lastChild, lastClass = inviteAgent.lastChild.nodeType === 1 ? lastChild.getAttribute("class") : null, prepOutput = function browser_content_agentManagement_inviteComplete_prepOutput(output) {
                    if (invitation.status === "accepted") {
                        output.appendText("Invitation accepted!", true);
                        output.setAttribute("class", "accepted");
                        util.audio("invite");
                    } else if (invitation.status === "declined") {
                        output.appendText("Invitation declined. :(", true);
                        output.setAttribute("class", "error");
                    } else if (invitation.status === "ignored") {
                        output.appendText("Invitation ignored.", true);
                        output.setAttribute("class", "error");
                    }
                };
                footer.style.display = "none";
                if (delay !== undefined) {
                    delay.parentNode.removeChild(delay);
                }
                inviteAgent.style.display = "block";
                if ((error === null || error === undefined) && lastClass !== "accepted" && lastClass !== "error") {
                    const p = document.createElement("p");
                    prepOutput(p);
                    inviteAgent.appendChild(p);
                } else if (error !== null && error !== undefined) {
                    prepOutput(error);
                }
            }
        },
        /* Receive an invitation from another agent */ inviteReceive: function browser_content_agentManagement_inviteReceive(invitation) {
            const agentInvite = invitation.agentRequest, config = {
                agent: browser.identity.hashDevice,
                agentIdentity: false,
                agentType: "device",
                closeHandler: agent_management.events.inviteDecline,
                content: null,
                height: 300,
                id: invitation.agentRequest.modal,
                inputs: [
                    "cancel",
                    "confirm",
                    "close"
                ],
                read_only: false,
                share: browser.identity.hashDevice,
                text_value: JSON.stringify(invitation),
                title_supplement: `User ${agentInvite.nameUser}`,
                type: "invite-ask",
                width: 500
            };
            modal_configuration.modals["invite-ask"](null, config);
            util.audio("invite");
        },
        /* Routes invitation messaging from the network to the appropriate method. */ inviteTransmissionReceipt: function browser_content_agentManagement_inviteTransmissionReceipt(socketData) {
            const invitation = socketData.data, modal = document.getElementById(invitation.agentRequest.modal);
            if (invitation.action === "invite-complete") {
                agent_management.tools.inviteComplete(invitation, modal);
            } else {
                if (modal !== null) {
                    // there should only be one invitation at a time from a given agent otherwise there is spam
                    return;
                }
                agent_management.tools.inviteReceive(invitation);
            }
        },
        /* Receives agent data from the terminal for processing in the browser. */ modifyReceive: function browser_content_agentManagement_modifyReceive(socketData) {
            const data = socketData.data;
            if (data.action === "add") {
                const addAgents = function browser_content_agentManagement_receive_addAgents(agentType) {
                    const keys = Object.keys(data.agents[agentType]), keyLength = keys.length;
                    if (keyLength > 0) {
                        let a = 0;
                        do {
                            if (browser.agents[agentType][keys[a]] === undefined) {
                                browser.agents[agentType][keys[a]] = data.agents[agentType][keys[a]];
                                agent_management.tools.addAgent({
                                    hash: keys[a],
                                    name: data.agents[agentType][keys[a]].name,
                                    type: agentType
                                });
                            }
                            a = a + 1;
                        }while (a < keyLength)
                    }
                };
                if (data.identity !== null) {
                    browser.identity.hashUser = data.identity.hashUser;
                    browser.identity.nameUser = data.identity.nameUser;
                }
                addAgents("device");
                addAgents("user");
            } else if (data.action === "delete") {
                const deleteAgents = function browser_content_agentManagement_receive_deleteAgents(agentType) {
                    const keys = Object.keys(data.agents[agentType]), keyLength = keys.length, property = `hash${common.capitalize(agentType)}`;
                    if (keyLength > 0) {
                        let a = 0;
                        do {
                            if (keys[a] === browser.identity[property]) {
                                agent_management.tools.deleteAgent(data.agentFrom, agentType);
                            } else {
                                agent_management.tools.deleteAgent(keys[a], agentType);
                            }
                            a = a + 1;
                        }while (a < keyLength)
                    }
                };
                deleteAgents("device");
                deleteAgents("user");
            } else if (data.action === "modify") {
                const shareContent = function browser_content_agentManagement_receive_shareContent(agentName, agentType) {
                    const shareModals = document.getModalsByModalType("shares");
                    let shareLength = shareModals.length, body = null;
                    if (shareLength > 0) {
                        do {
                            shareLength = shareLength - 1;
                            if (shareModals[shareLength].dataset.agent === agentName && shareModals[shareLength].dataset.agenttype === agentType || agentType === "" && shareModals[shareLength].getElementsByTagName("button")[0].firstChild.textContent === "⌘ All Shares") {
                                body = shareModals[shareLength].getElementsByClassName("body")[0];
                                body.appendText("", true);
                                body.appendChild(share.content(agentName, agentType));
                            }
                        }while (shareLength > 0)
                    }
                }, modifyAgents = function browser_content_agentManagement_receive_modifyAgents(agentType) {
                    const keys = Object.keys(data.agents[agentType]), keyLength = keys.length;
                    if (keyLength > 0) {
                        let a = 0;
                        do {
                            if (browser.agents[agentType][keys[a]] !== undefined) {
                                browser.agents[agentType][keys[a]] = data.agents[agentType][keys[a]];
                                shareContent(keys[a], agentType);
                            }
                            a = a + 1;
                        }while (a < keyLength)
                        shareContent("", agentType);
                    }
                };
                modifyAgents("device");
                modifyAgents("user");
                shareContent("", "");
            }
        }
    }
};
export default agent_management;
