var apx = apx || {};

apx.privatri = {};
apx.privatri.templates = {};

const apiUrl = "http://admin.apxtri.farm.test/api/apxtri/privatri"
const tribe = "apxtri";

apx.privatri.loadwco = async (id, dataObj = {}, ctx = null) => {
    // check if not authenticate, do nothing cause by default screensignin and wait authentification
    //       if     authenticate, if url xhash then redirect if no url then change wco-link=screenmyworld
    // if (dayjs(apx.data.headers.xdays).diff(dayjs(), "hours") >= 24) apx.apxauth.checkisauth();
    //load main.mustache of the component
    //when wco-xxx change it run this function
    console.log(
        `Load wconame:privatri apx.privatri.loadwco with id:${id} and ctx: ${JSON.stringify(
            ctx
        )}`
    );

    const templatesObj = JSON.parse(localStorage.getItem("admin")).tpl;

    const template = Object.entries(templatesObj).find(([key]) => key.toLowerCase() === `privatri${id}`.toLocaleLowerCase())?.[1];
    
    return Mustache.render(template, dataObj);
};

async function getOldestPrivatriids(db, storeName) {
    const keysArray = await apx.indexedDB.getAllKeys(db, storeName);
    
    const oldestPerUuid = {};

    for (const key of keysArray) {
        const [uuid, timestampStr] = key.split("_");
        const timestamp = Number(timestampStr);

        if (!oldestPerUuid[uuid] || timestamp < oldestPerUuid[uuid].timestamp) {
            oldestPerUuid[uuid] = { key, timestamp };
        };
    };

    const oldestKeysArray = Object.values(oldestPerUuid).map(obj => obj.key)

    const threadsArray = [];

    for (key of oldestKeysArray) {
        threadsArray.push(await apx.indexedDB.get(db, storeName, key));
    };

    return threadsArray;
};

apx.privatri.syncronizeBackend = async (alias, lastConnection) => {
    const threadsArray = await getOldestPrivatriids("privatri", "messages");

    for (const threadObj of threadsArray) {
        try {
            const response = await fetch(`${apiUrl}/${tribe}/${threadObj.thread}?since=${lastConnection}`);
    
            if (response.ok === false) {
                throw new Error("HTTP error");
            };
    
            console.log(response);

            // for (const message of response) {
            //     await apx.indexedDB.set("privatri", "messages", message);
            // };
        } catch (error) {
            const displayToastAlert = async (message) => {
                return await apx.privatri.loadwco("toastAlert", { message });
            };

            document.querySelector("body").insertAdjacentHTML("beforeend", await displayToastAlert("An error occurred while synchronizing messages. Please try again later."));
        };
    };
};

apx.privatri.templates.scripts = {
    createThread: async () => {
        const bodyEl = document.querySelector("body");
        const autoDeletionBtnElArray = document.querySelectorAll("li.autoDeletionBtn");

        const displayToastAlert = async (message) => {
            return await apx.privatri.loadwco("toastAlert", { message });
        };
        
        autoDeletionBtnElArray.forEach(btn => {
            btn.addEventListener("click", () => {
                autoDeletionBtnElArray.forEach(btn => btn.classList.remove("bg-base-200"));
                btn.classList.add("bg-base-200");
            });
        });
        
        document.querySelector("#createThreadBtn").addEventListener("click", async () => {
            const { publicKey, privateKey } = await apx.crypto.genKey();

            const messageObj = await (async (publicKey) => {
                const uuid = apx.crypto.genUUID();
                const timestamp = Date.now();
                const alias = await apx.crypto.encryptMessage(JSON.parse(localStorage.getItem("admin")).headers.xalias, publicKey);
        
                return {
                    privatriid: `${uuid}_${timestamp}`,
                    thread: uuid,
                    timestamp: timestamp,
                    owner: alias,
                    title: await apx.crypto.encryptMessage(document.querySelector("#threadNameInput").value, publicKey),
                    sender_alias: alias,
                    publicKey: publicKey,
                    aliases: [
                        alias
                    ],
                    message: await apx.crypto.encryptMessage(document.querySelector("#threadDescriptionInput").value, publicKey),
                    dt_autodestruction: (() => {
                        const selectedBtn = Array.from(autoDeletionBtnElArray).find(btn => btn.classList.contains("bg-base-200"));
                        return parseInt(selectedBtn ? selectedBtn.getAttribute("data-auto-deletion") : 0, 10);
                    })(),
                    urgencydeletion: document.querySelector('input[type="checkbox"].toggle').checked
                };
            })(publicKey);
        
            try {
                const response = await fetch(`${apiUrl}/${tribe}/${messageObj.thread}`, {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        "xdays": admin.headers.xdays,
                        "xalias": admin.headers.xalias,
                        "xlang": admin.headers.xlang,
                        "xtribe": admin.headers.xtribe,
                        "xapp": admin.headers.xapp,
                        "xuuid": admin.headers.xuuid
                    },
                    body: JSON.stringify(messageObj)
                });

                if (response.ok === false) {
                    throw new Error("HTTP error");
                };

                await apx.indexedDB.set("privatri", "threads", { uuid: messageObj.thread, privateKey: privateKey });
                await apx.indexedDB.set("privatri", "messages", messageObj);

                bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("Thread created successfully."));
            } catch (error) {
                bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("An error occurred while creating the thread. Please try again later."));
            };
        });
    },
    inviteAlias: async () => {
        const url = "https://www.facebook.com/";

        const bodyEl = document.querySelector("body");
        const qrCodeCanvasEl = document.querySelector("#qrCodeCanvas");
        const invitationLinkInputEl = document.querySelector("#invitationLinkInput");

        const displayToastAlert = async (message) => {
            return await apx.privatri.loadwco("toastAlert", { message });
        };
        
        const qrCode = new QRCodeStyling({
            width: 425,
            height: 425,
            type: "svg",
            data: url,
            image: "static/img/icons/privatri.png",
            dotsOptions: {
                color: "#ffffff",
                type: "rounded"
            },
            backgroundOptions: {
                color: getComputedStyle(bodyEl).backgroundColor || "#000000",
            },
            imageOptions: {
                crossOrigin: "anonymous",
                margin: 20
            }
        });
        
        qrCode.append(qrCodeCanvasEl);

        invitationLinkInputEl.value = url;

        copyBtn.addEventListener("click", async () => {
            navigator.clipboard.writeText(invitationLinkInputEl.value);

            bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("Invitation link copied to clipboard."));

            setTimeout(() => {
                bodyEl.lastElementChild.remove();
            }, 3000);
        });
    },
    threadAliasList: async () => {
        const bodyEl = document.querySelector("body");
        const aliasListContainerEl = document.querySelector("#aliasListContainer");

        let aliasesArray = [];

        const newAlias = async (alias) => {
            return await apx.privatri.loadwco("alias", { alias });
        };

        const displayToastAlert = async (message) => {
            return await apx.privatri.loadwco("toastAlert", { message });
        };

        const params = new URLSearchParams(window.location.search);
        const uuid = params.get("uuid");

        const privateKey = (await apx.indexedDB.get("privatri", "threads", uuid)).privateKey;
        
        const privatriidArray = await getOldestPrivatriids("privatri", "messages");
        
        privatriidArray.forEach(async privatriid => {
            if (privatriid.thread === uuid) {
                messageObj = privatriid;
                aliasesArray = messageObj.aliases;
                const ownerAlias = messageObj.owner;
                
                for (const alias of aliasesArray) {
                    aliasListContainerEl.insertAdjacentHTML("beforeend", await newAlias({
                        decrypted: (await apx.crypto.decryptMessage(alias, privateKey)).data,
                        crypted: alias
                    }));
                };

                document.querySelectorAll("button.removeAliasBtn").forEach(btn => {
                    btn.addEventListener("click", async () => {
                        if (JSON.parse(localStorage.getItem("admin")).headers.xalias === (await apx.crypto.decryptMessage(ownerAlias, privateKey)).data) {
                            if (btn.getAttribute("data-alias") !== ownerAlias) {
                                const alias = btn.getAttribute("data-alias");
                                aliasesArray = aliasesArray.filter(a => a !== alias);
                                btn.parentElement.parentElement.remove();
                    
                                privatriidArray.forEach(async privatriid => {
                                    if (privatriid.split("_")[0] === uuid) {
                                        const messageObj = await apx.indexedDB.get("privatri", "messages", privatriid);
                                        messageObj.aliases = aliasesArray;
                                        
                                        await apx.indexedDB.set("privatri", "messages", messageObj);
                                    };
                                });
                            } else {
                                bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("You cannot remove the owner of the thread."));

                                setTimeout(() => {
                                    bodyEl.lastElementChild.remove();
                                }, 3000);
                            };
                        } else {
                            bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("You don't have the permissions to remove this alias."));

                            setTimeout(() => {
                                bodyEl.lastElementChild.remove();
                            }, 3000);
                        };
                    });
                });
            };
        });
    },
    threadSettings: async () => {
        const bodyEl = document.querySelector("body");
        const threadNameInputEl = document.querySelector("#threadNameInput");
        const autoDeletionBtnElArray = document.querySelectorAll("li.autoDeletionBtn");
        const applyModificationsBtnEl = document.querySelector("#applyModificationsBtn");

        const displayToastAlert = async (message) => {
            return await apx.privatri.loadwco("toastAlert", { message });
        };

        let messageObj = {};

        const params = new URLSearchParams(window.location.search);
        const uuid = params.get("uuid");

        const privateKey = (await apx.indexedDB.get("privatri", "threads", uuid)).privateKey;
        
        const privatriidArray = await getOldestPrivatriids("privatri", "messages");
        let ownerAlias = "";
        
        privatriidArray.forEach(async privatriid => {
            if (privatriid.thread === uuid) {
                messageObj = privatriid;
                ownerAlias = messageObj.owner;
                
                threadNameInputEl.value = (await apx.crypto.decryptMessage(messageObj.title, privateKey)).data;

                (Array.from(autoDeletionBtnElArray).find(el => el.getAttribute("data-auto-deletion") === String(messageObj.dt_autodestruction))).classList.add("bg-base-200");
            
                if (messageObj.urgencydeletion === true) {
                    document.querySelector('input[type="checkbox"].toggle').checked = true;
                };
            };
        });

        applyModificationsBtnEl.addEventListener("click", async () => {
            if (JSON.parse(localStorage.getItem("admin")).headers.xalias === (await apx.crypto.decryptMessage(ownerAlias, privateKey)).data) {
                messageObj.title = await apx.crypto.encryptMessage(threadNameInputEl.value, privateKey);
                messageObj.dt_autodestruction = (() => {
                    const selectedBtn = Array.from(autoDeletionBtnElArray).find(btn => btn.classList.contains("bg-base-200"));
                    return parseInt(selectedBtn ? selectedBtn.getAttribute("data-auto-deletion") : 0, 10);
                })();
                messageObj.urgencydeletion = document.querySelector('input[type="checkbox"].toggle').checked;

                await apx.indexedDB.set("privatri", "messages", messageObj);
            } else {
                bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("You don't have the permissions to edit this thread."));

                setTimeout(() => {
                    bodyEl.lastElementChild.remove();
                }, 3000);
            };
        });

        autoDeletionBtnElArray.forEach(btn => {
            btn.addEventListener("click", () => {
                autoDeletionBtnElArray.forEach(btn => btn.classList.remove("bg-base-200"));
                btn.classList.add("bg-base-200");
            });
        });
    }
};

apx.ready(async () => {
    document.querySelector("body").innerHTML = await apx.privatri.loadwco("main", JSON.parse(localStorage.getItem("admin")).tpldata.privatri_main_privatri);
    
    const bodyEl = document.querySelector("body");
    const searchInputEl = document.querySelector("#threadSearchBar");
    const threadFilterOptionsElArray = document.querySelector("#threadFilterOptions").querySelectorAll("li");
    const threadsContainerEl = document.querySelector("#threadsContainer");
    const threadPageEl = document.querySelector("#threadPage");
    const messageInputEl = document.getElementById("messageInput");
    const messagesContainerEl = document.querySelector("#messagesContainer");
    const attachmentsInputEl = document.querySelector("#attachmentsInput");

    await (async () => {
        const lastConnection = JSON.parse(localStorage.getItem("lastConnection")) || Date.now();
    
        // await apx.privatri.syncronizeBackend(apx.data.headers.xalias, lastConnection);
    
        const privatriidArray = await getOldestPrivatriids("privatri", "messages");
        console.log(privatriidArray);
    
        const thread = async (name, uuid) => {
            return await apx.privatri.loadwco("thread", { uuid, name });
        };
    
        for (const privatriidObj of privatriidArray) {
            const obj = await apx.indexedDB.get("privatri", "messages", privatriidObj.privatriid)
            
            const privateKey = (await apx.indexedDB.get("privatri", "threads", obj.thread)).privateKey;
            const name = (await apx.crypto.decryptMessage(obj.title, privateKey)).data;
    
            threadsContainerEl.insertAdjacentHTML("beforeend", await thread(name, obj.thread));
        };
    
        Array.from(threadsContainerEl.children).forEach(child => {
            child.addEventListener("click", async () => {
                const uuid = child.getAttribute("data-uuid");
    
                const messagesObj = await new Promise((resolve, reject) => {
                    const request = indexedDB.open("privatri", 1);
    
                    request.onsuccess = (event) => {
                        const db = event.target.result;
    
                        const transaction = db.transaction("messages", "readonly");
                        const store = transaction.objectStore("messages");
                        const cursorRequest = store.openCursor();
    
                        const result = [];
                        cursorRequest.onsuccess = (event) => {
                            const cursor = event.target.result;
    
                            if (cursor) {
                                const obj = cursor.value;
                                const keyUuid = obj.privatriid.split("_")[0];
    
                                if (keyUuid === uuid) {
                                    result.push(obj);
                                };
                                cursor.continue();
                            } else {
                                resolve(result);
                            };
                        };
    
                        cursorRequest.onerror = (event) => reject(event);
                    };
    
                    request.onerror = (event) => reject(event);
                });
    
                threadPageEl.setAttribute("data-uuid", uuid);
                threadPageEl.querySelector("#threadName").innerText = (await apx.crypto.decryptMessage(messagesObj[0].title, (await apx.indexedDB.get("privatri", "threads", uuid)).privateKey)).data;
    
                messagesContainerEl.innerHTML = "";
    
                let privateKey = "";
    
                for (const message of messagesObj) {
                    if (privateKey === "") {
                        privateKey = (await apx.indexedDB.get("privatri", "threads", message.thread)).privateKey;
                    };
    
                    const decryptedMessage = (await apx.crypto.decryptMessage(message.message, privateKey)).data;
    
                    let decryptedAttachments = [];
    
                    if (message.attachments !== undefined) {
                        decryptedAttachments = await (async () => {
                            const attachmentsArray = [];
        
                            if (message.attachments.length > 0) {
                                for (const attachment of message.attachments) {
                                    attachmentsArray.push({
                                        fileType: attachment.fileType,
                                        filename: attachment.filename,
                                        content: (await apx.crypto.decryptMessage(attachment.content, privateKey)).data
                                    });
                                };
                            };
        
                            return attachmentsArray;
                        })();
                    };
    
                    messagesContainerEl.insertAdjacentHTML("beforeend", await sendNewMessage(message.timestamp, decryptedMessage, decryptedAttachments));
                };
            });
        });

        threadsContainerEl.children[0]?.click();
        
        document.querySelectorAll("a").forEach(link => {
            link.addEventListener("click", async (event) => {
                event.preventDefault();

                window.history.replaceState({}, document.title, window.location.pathname);
    
                const templateName = link.getAttribute("data-template");
    
                if (templateName === "threadAliasList" || templateName === "threadSettings") {
                    window.history.pushState({}, "", `${window.location.pathname}?uuid=${threadPageEl.getAttribute("data-uuid")}`);
                };
    
                bodyEl.innerHTML = await apx.privatri.loadwco(templateName);
    
                await apx.privatri.templates.scripts[templateName]();
            });
        });
    })();

    function formatDate(timestamp) {
        const date = new Date(timestamp);
        const day = String(date.getDate()).padStart(2, "0");
        const month = String(date.getMonth() + 1).padStart(2, "0");
        const year = date.getFullYear();
        const hours = String(date.getHours()).padStart(2, "0");
        const minutes = String(date.getMinutes()).padStart(2, "0");

        return `${day}/${month}/${year} ${hours}:${minutes}`;
    };

    searchInputEl.addEventListener("input", () => {
        const value = searchInputEl.value.toLowerCase();

        Array.from(threadsContainerEl.children).forEach(child => {
            if (child.querySelector("li > div").textContent.toLowerCase().includes(value)) {
                child.style.display = "block";
            } else {
                child.style.display = "none";
            };
        });
    });

    threadFilterOptionsElArray.forEach(option => {
        option.addEventListener("click", async () => {
            const filter = option.getAttribute("data-filter");

            if (filter === "date") {
                Array.from(threadsContainerEl.children).sort((a, b) => {
                    return a.querySelector("li > span").getAttribute("data-timestamp") - b.querySelector("li > span").getAttribute("data-timestamp");
                }).forEach(child => {
                    threadsContainerEl.appendChild(child);
                });
            } else if (filter === "name") {
                Array.from(threadsContainerEl.children).sort((a, b) => {
                    return a.querySelector("li > div").textContent.localeCompare(b.querySelector("li > div").textContent);
                }).forEach(child => {
                    threadsContainerEl.appendChild(child);
                });
            };
        });
    });

    const sendNewMessage = async (timestamp, message, attachmentsArray) => {
        const messageTemplate = await apx.privatri.loadwco("message", { timestamp, message, date: formatDate(timestamp) });

        const tempNode = document.createElement("div");
        tempNode.innerHTML = messageTemplate;
        const messageNode = tempNode.firstElementChild;

        attachmentsArray.forEach(attachment => {
            messageNode.querySelector("div.attachmentsContainer").insertAdjacentHTML("beforeend", `<img onclick="attachEventDisplayAttachment(this)" class="w-20 h-20 object-cover rounded" src="data:${attachment.fileType};base64,${attachment.content}" alt="${attachment.filename}"/>`);
        });
        
        return messageNode.outerHTML;
    };

    const editMessage = async (timestamp, message) => {
        return await apx.privatri.loadwco("editMessage", { message, date: formatDate(timestamp) });
    };

    const displayToastAlert = async (message) => {
        return await apx.privatri.loadwco("toastAlert", { message });
    };

    sendMessageBtn.addEventListener("click", async () => {
        const message = messageInputEl.value.trim();

        if (message !== "") {
            const messageObj = await (async (publicKey) => {
                const timestamp = Date.now();
                const alias = await apx.crypto.encryptMessage(JSON.parse(localStorage.getItem("admin")).headers.xalias, publicKey);
        
                return {
                    privatriid: `${threadPageEl.getAttribute("data-uuid")}_${timestamp}`,
                    timestamp: timestamp,
                    sender_alias: alias,
                    message: await apx.crypto.encryptMessage(message, publicKey),
                    attachments: await (async () => {
                        const attachmentsArray = [];
                        const localAttachmentsArray = JSON.parse(sessionStorage.getItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`)) || [];

                        if (localAttachmentsArray.length > 0) {
                            for (const attachment of localAttachmentsArray) {
                                attachmentsArray.push(
                                    {
                                        fileType: attachment.fileType,
                                        filename: attachment.filename,
                                        content: await apx.crypto.encryptMessage(attachment.content, publicKey)
                                    }
                                );
                            };
                        };

                        return attachmentsArray;
                    })()
                };
            })((await apx.indexedDB.get("privatri", "messages", `${threadPageEl.getAttribute("data-uuid")}_${messagesContainerEl.firstElementChild.getAttribute("data-timestamp")}`)).publicKey);
            
            const newMessageHTML = await sendNewMessage(messageObj.timestamp, message, JSON.parse(sessionStorage.getItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`)) || []);

            sessionStorage.removeItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`);
            
            messagesContainerEl.insertAdjacentHTML("beforeend", newMessageHTML);
            
            messageInputEl.value = "";

            try {
                const response = await fetch(`${apiUrl}/`);

                if (response.ok === false) {
                    throw new Error("HTTP error");
                };

                await apx.indexedDB.set("privatri", "messages", messageObj);
            } catch (error) {
                bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("An error occurred while sending the message. Please try again later."));
            };
        };
    });

    window.addEventListener("beforeunload", () => {
        localStorage.setItem("lastConnection", JSON.stringify(Date.now()));
    });

    window.attachDeleteMessageEvent = async function attachDeleteMessageEvent(btn) {
        const messageEl = btn.parentElement.parentElement.parentElement;

        const privateKey = (await apx.indexedDB.get("privatri", "threads", threadPageEl.getAttribute("data-uuid"))).privateKey;

        const signatureMessage = `${JSON.parse(localStorage.getItem("admin")).headers.xalias}_${threadPageEl.getAttribute("data-uuid")}_${messageEl.getAttribute("data-timestamp")}`;
        const signature = await apx.crypto.sign(signatureMessage, privateKey);
        
        let verified = false;

        // try {
        //     verified = await fetch("", {
        //         method: "GET",
        //         body: JSON.stringify({
        //             message: signatureMessage,
        //             signature: signature,
        //             uuid: threadPageEl.getAttribute("data-uuid"),
        //             timestamp: messageEl.getAttribute("data-timestamp"),
        //         })
        //     });
        // } catch (error) {
        //     console.error("Error while verifying signature:", error);
        // };

        const authorAlias = (await apx.crypto.decryptMessage((await apx.indexedDB.get("privatri", "messages", `${threadPageEl.getAttribute("data-uuid")}_${messageEl.getAttribute("data-timestamp")}`)).sender_alias, privateKey)).data;

        if ((JSON.parse(localStorage.getItem("admin")).headers.xalias === authorAlias) && (verified === true)) {
            await apx.indexedDB.del("privatri", "messages", `${threadPageEl.getAttribute("data-uuid")}_${messageEl.getAttribute("data-timestamp")}`);
        
            messageEl.remove();
        } else {
            bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("You don't have the permissions to delete this message."));

            setTimeout(() => {
                bodyEl.lastElementChild.remove();
            }, 3000);
        };
    };

    window.attachEditMessageEvent = async function attachEditMessageEvent(btn) {
        const messageEl = btn.parentElement.parentElement.parentElement;
    
        const authorAlias = (await apx.crypto.decryptMessage((await apx.indexedDB.get("privatri", "messages", `${threadPageEl.getAttribute("data-uuid")}_${messageEl.getAttribute("data-timestamp")}`)).sender_alias, (await apx.indexedDB.get("privatri", "threads", threadPageEl.getAttribute("data-uuid"))).privateKey)).data;
        
        if (JSON.parse(localStorage.getItem("admin")).headers.xalias === authorAlias) {
            const messageValue = messageEl.querySelector("div.message").innerText;

            const attachmentsArray = (() => {
                const attachmentsArray = [];

                messageEl.querySelector("div.attachmentsContainer").querySelectorAll("img").forEach(img => {
                    attachmentsArray.push(
                        {
                            fileType: img.getAttribute("src").match(/^data:(.*);base64,/)[1],
                            filename: img.getAttribute("alt"),
                            content: img.getAttribute("src").split(",")[1]
                        }
                    );
                });

                return attachmentsArray;
            })();

            messageEl.innerHTML = await editMessage(parseInt(messageEl.getAttribute("data-timestamp"), 10), messageEl.querySelector("div.message").innerText);

            messageEl.querySelector("button.cancelEditBtn").addEventListener("click", async () => {
                const messageObj = await apx.indexedDB.get("privatri", "messages", `${threadPageEl.getAttribute("data-uuid")}_${messageEl.getAttribute("data-timestamp")}`);

                messageEl.innerHTML = await sendNewMessage(messageObj.timestamp, messageValue, attachmentsArray);
            });

            messageEl.querySelector("button.saveEditBtn").addEventListener("click", async () => {
                const newMessageValue = messageEl.querySelector("textarea").value.trim();

                if (newMessageValue !== "") {
                    const privateKey = (await apx.indexedDB.get("privatri", "threads", threadPageEl.getAttribute("data-uuid"))).privateKey;

                    const messageObj = await apx.indexedDB.get("privatri", "messages", `${threadPageEl.getAttribute("data-uuid")}_${messageEl.getAttribute("data-timestamp")}`);

                    messageObj.message = await apx.crypto.encryptMessage(newMessageValue, privateKey),

                    await apx.indexedDB.set("privatri", "messages", messageObj);

                    messageEl.innerHTML = await sendNewMessage(messageObj.timestamp, newMessageValue, attachmentsArray);
                };
            });
        } else {
            bodyEl.insertAdjacentHTML("beforeend", await displayToastAlert("You don't have the permissions to edit this message."));

            setTimeout(() => {
                bodyEl.lastElementChild.remove();
            }, 3000);
        };
    };

    window.attachEventDisplayAttachment = function(img) {
        let overlay = document.getElementById("imageOverlay");

        if (overlay === null) {
            overlay = document.createElement('div');

            overlay.id = "imageOverlay";
            overlay.style.position = "fixed";
            overlay.style.top = 0;
            overlay.style.left = 0;
            overlay.style.width = "100vw";
            overlay.style.height = "100vh";
            overlay.style.background = "rgba(0, 0, 0, 0.75)";
            overlay.style.display = "flex";
            overlay.style.alignItems = "center";
            overlay.style.justifyContent = "center";
            overlay.style.zIndex = 999;

            overlay.onclick = () => {
                overlay.remove();
            };

            document.body.appendChild(overlay);
        } else {
            overlay.innerHTML = "";
            overlay.style.display = "flex";
        };

        const fullScreenImage = document.createElement("img");

        fullScreenImage.src = img.src;
        fullScreenImage.alt = img.alt;
        fullScreenImage.style.maxWidth = "90vw";
        fullScreenImage.style.maxHeight = "90vh";
        overlay.appendChild(fullScreenImage);
    };

    document.querySelector("#attachmentsBtn").addEventListener("click", () => {
        attachmentsInputEl.click();
    });

    attachmentsInputEl.addEventListener("change", async () => {
        const filesArray = Array.from(attachmentsInputEl.files);
        const maxFileSize = 5 * 1024 * 1024;
        const maxSize = 512;

        for (const file of filesArray) {
            if (file.size <= maxFileSize) {
                const attachmentObj = await new Promise((resolve, reject) => {
                    const attachmentObj = {
                        fileType: file.type,
                        filename: file.name,
                        content: ""
                    };

                    const img = new Image();
                    
                    img.onload = () => {
                        if (img.width > maxSize || img.height > maxSize) {
                            let width = img.width;
                            let height = img.height;

                            if (width > maxSize) {
                                height *= maxSize / width;
                                width = maxSize;
                            };

                            if (height > maxSize) {
                                width *= maxSize / height;
                                height = maxSize;
                            };

                            const canvas = document.createElement("canvas");
                            canvas.width = width;
                            canvas.height = height;

                            const ctx = canvas.getContext("2d");

                            ctx.drawImage(img, 0, 0, width, height);

                            canvas.toBlob(blob => {
                                const reader = new FileReader();

                                reader.onload = (event) => {
                                    attachmentObj.content = event.target.result.split(",")[1];

                                    resolve(attachmentObj);
                                };

                                reader.onerror = reject;
                                reader.readAsDataURL(blob);
                            }, "image/jpeg", 0.8);
                        } else {
                            const reader = new FileReader();

                            reader.onload = (event) => {
                                attachmentObj.content = event.target.result.split(",")[1];

                                resolve(attachmentObj);
                            };

                            reader.onerror = reject;
                            reader.readAsDataURL(file);
                        };
                    };

                    img.onerror = reject;
                    img.src = URL.createObjectURL(file);

                    return attachmentObj;
                });

                if (sessionStorage.getItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`) === null) {
                    sessionStorage.setItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`, JSON.stringify([attachmentObj]));
                } else {
                    const attachmentsArray = JSON.parse(sessionStorage.getItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`));
                    attachmentsArray.push(attachmentObj);

                    sessionStorage.setItem(`attachmentsArray_${threadPageEl.getAttribute("data-uuid")}`, JSON.stringify(attachmentsArray));
                };
            };
        };
    });
});