if (localStorage.getItem("DONOTSHARE-secretkey") === null) {
    window.location.replace("/login")
    document.body.innerHTML = "Redirecting..."
    throw new Error();
}
if (localStorage.getItem("DONOTSHARE-password") === null) {
    window.location.replace("/login")
    document.body.innerHTML = "Redirecting..."
    throw new Error();
}

if (localStorage.getItem("CACHE-username") !== null) {
    //document.getElementById("usernameBox").innerText = localStorage.getItem("CACHE-username")
}

let remote = localStorage.getItem("homeserverURL")
if (remote == null) {
    localStorage.setItem("homeserverURL", "https://notes.hectabit.org")
    remote = "https://notes.hectabit.org"
}

function formatBytes(a, b = 2) { if (!+a) return "0 Bytes"; const c = 0 > b ? 0 : b, d = Math.floor(Math.log(a) / Math.log(1000)); return `${parseFloat((a / Math.pow(1000, d)).toFixed(c))} ${["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][d]}` }

let secretkey = localStorage.getItem("DONOTSHARE-secretkey")
let password = localStorage.getItem("DONOTSHARE-password")
let currentFontSize = 16
let markdowntoggle = false

let burgerButton = document.getElementById("burgerButton")
let backButton = document.getElementById("backButton")
let usernameBox = document.getElementById("usernameBox")
let optionsCoverDiv = document.getElementById("optionsCoverDiv")
let optionsDiv = document.getElementById("optionsDiv")
let errorDiv = document.getElementById("errorDiv")
let errorMessageThing = document.getElementById("errorMessageThing")
let closeErrorButton = document.getElementById("closeErrorButton")
let cancelErrorButton = document.getElementById("cancelErrorButton")
let errorInput = document.getElementById("errorInput")
let exitThing = document.getElementById("exitThing")
let exitSessionsThing = document.getElementById("exitSessionsThing")
let sessionManagerButton = document.getElementById("sessionManagerButton")
let importNotesButton = document.getElementById("importNotesButton")
let sessionManagerDiv = document.getElementById("sessionManagerDiv")
let importNotesDiv = document.getElementById("importDiv")
let sessionDiv = document.getElementById("sessionDiv")
let deleteMyAccountButton = document.getElementById("deleteMyAccountButton")
let storageThing = document.getElementById("storageThing")
let storageProgressThing = document.getElementById("storageProgressThing")
let usernameThing = document.getElementById("usernameThing")
let logOutButton = document.getElementById("logOutButton")
let notesBar = document.getElementById("notesBar")
let notesDiv = document.getElementById("notesDiv")
let newNote = document.getElementById("newNote")
let noteBox = document.getElementById("noteBox")
let noteBoxDiv = document.getElementById("noteBoxDiv")
let loadingStuff = document.getElementById("loadingStuff")
let exportNotesButton = document.getElementById("exportNotesButton")
let markdown = document.getElementById('markdown');
let textSizeBox = document.getElementById('textSizeBox');
let textPlusBox = document.getElementById('textPlusBox');
let textMinusBox = document.getElementById('textMinusBox');
let wordCountBox = document.getElementById('wordCountBox');
let removeBox = document.getElementById("removeBox")
let importFile = document.getElementById("importFile")

let selectedNote = 0
let timer
let waitTime = 400
let indiv = false
let mobile = false

if (/Android|iPhone|iPod/i.test(navigator.userAgent)) {
    mobile = true
    noteBoxDiv.classList.add("mobile");
    noteBoxDiv.style.width = "0px";
    notesBar.style.width = "calc(100% + 7.5px)"
    noteBoxDiv.readOnly = true
    noteBox.style.fontSize = "18px"
    noteBoxDiv.classList.add("hidden")

    let touchstartX, touchstartY, touchendX, touchendY

    notesBar.addEventListener("touchstart", function (event) {
        touchstartX = event.changedTouches[0].screenX;
        touchstartY = event.changedTouches[0].screenY;
    }, false);

    notesBar.addEventListener("touchend", function (event) {
        touchendX = event.changedTouches[0].screenX;
        touchendY = event.changedTouches[0].screenY;
        if (touchendX < touchstartX - 75) {
            handleGesture();
        }
    }, false);

    noteBox.addEventListener("touchstart", function (event) {
        touchstartX = event.changedTouches[0].screenX;
        touchstartY = event.changedTouches[0].screenY;
    }, false);

    noteBox.addEventListener("touchend", function (event) {
        touchendX = event.changedTouches[0].screenX;
        touchendY = event.changedTouches[0].screenY;
        if (touchendX > touchstartX + 75) {
            handleGesture();
        } else if (touchendX < touchstartX - 75) {
            enableMarkdown();
        }
    }, false);

    markdown.addEventListener("touchstart", function (event) {
        touchstartX = event.changedTouches[0].screenX;
        touchstartY = event.changedTouches[0].screenY;
    }, false);

    markdown.addEventListener("touchend", function (event) {
        touchendX = event.changedTouches[0].screenX;
        touchendY = event.changedTouches[0].screenY;
        if (touchendX > touchstartX + 75) {
            disableMarkdown();
        } else if (touchendX < touchstartX - 75) {
            disableMarkdown();
        }
    }, false);
}

function handleGesture() {
    if (indiv) {
        indiv = false
        notesBar.style.width = "calc(100% + 7.5px)";
        noteBoxDiv.style.width = "0px"
        if (selectedNote !== 0) {
            noteBoxDiv.readOnly = true
        }
        notesDiv.classList.remove("hidden")
        noteBoxDiv.classList.add("hidden")
        burgerButton.classList.remove("hidden")
        backButton.classList.add("hidden")
        newNote.classList.remove("hidden")
    } else {
        indiv = true
        noteBoxDiv.style.width = "100%";
        notesBar.style.width = "0px"
        if (selectedNote !== 0) {
            noteBoxDiv.readOnly = false
        }
        notesDiv.classList.add("hidden")
        noteBoxDiv.classList.remove("hidden")
       	burgerButton.classList.add("hidden")
       	backButton.classList.remove("hidden")
        newNote.classList.add("hidden")
    }
}

noteBox.value = ""
noteBox.readOnly = true

let noteCount = 0

function displayError(message) {
    errorDiv.classList.remove("hidden")
    optionsCoverDiv.classList.remove("hidden")

    errorMessageThing.innerHTML = message
}

closeErrorButton.addEventListener("click", () => {
    errorDiv.classList.add("hidden")
    optionsCoverDiv.classList.add("hidden")
});
closeErrorButton.addEventListener("click", () => {
    errorDiv.classList.add("hidden")
    optionsCoverDiv.classList.add("hidden")
    errorInput.classList.add("hidden")
    cancelErrorButton.classList.add("hidden")
});

function updateFont() {
    currentFontSize = localStorage.getItem("SETTING-fontsize")
    noteBox.style.fontSize = currentFontSize + "px"
    textSizeBox.innerText = currentFontSize + "px"
    if (markdowntoggle) {
        markdown.srcdoc = "<!DOCTYPE html><html lang='en'><style>html { height: 100% } pre { white-space: pre-wrap; overflow-wrap: break-word; } body { white-space: pre-wrap; overflow-wrap: break-word; font-family: 'Inter', sans-serif; height: 100%; color: " + getComputedStyle(document.documentElement).getPropertyValue('--text-color') + "; font-size: " + currentFontSize + "px; }</style>" + marked.parse(noteBox.value) + "</html>";
    }
}

async function checknetwork() {
    fetch(remote + "/api/loggedin", {
        method: "POST",
        body: JSON.stringify({
            secretKey: localStorage.getItem("DONOTSHARE-secretkey"),
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
    .catch(() => {
        noteBox.readOnly = true
        noteBox.value = ""
        noteBox.placeholder = "You are currently offline."
        displayError("Failed to connect to the server.\nPlease check your internet connection.")
    })
    .then((response) => response)
    .then((response) => {
        if (response.status == 400) {
            displayError("Something went wrong! Signing you out...")
            closeErrorButton.classList.add("hidden")
            //usernameBox.innerText = ""
            setTimeout(function () {
                window.location.replace("/logout")
            }, 2500);
        } else if (response.status == 200) {
            updateUserInfo()
        } else {
            noteBox.readOnly = true
            noteBox.value = ""
            noteBox.placeholder = "You are currently offline."
            displayError("Failed to connect to the server.\nPlease check your internet connection.")
        }
    });
}

if (localStorage.getItem("SETTING-fontsize") === null) {
    localStorage.setItem("SETTING-fontsize", "16")
    updateFont()
} else {
    updateFont()
}

textPlusBox.addEventListener("click", () => {
    localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) + Number(1)))
    updateFont()
});
textMinusBox.addEventListener("click", () => {
    localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) - Number(1)))
    updateFont()
});


function truncateString(str, num) {
    if (str.length > num) {
        return str.slice(0, num) + "..";
    } else {
        return str;
    }
}


function updateUserInfo() {
    fetch(remote + "/api/userinfo", {
        method: "POST",
        body: JSON.stringify({
            secretKey: secretkey
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
        .then((response) => {
            async function doStuff() {
                if (response.status === 500) {
                    displayError("Something went wrong! Signing you out...")
                    closeErrorButton.classList.add("hidden")
                    //usernameBox.innerText = ""
                    setTimeout(function () {
                        window.location.replace("/logout")
                    }, 2500);
                } else {
                    let responseData = await response.json()
                    //usernameBox.innerText = responseData["username"]
                    usernameThing.innerText = "Username: " + responseData["username"]
                    storageThing.innerText = "You've used " + formatBytes(responseData["storageused"]) + " out of " + formatBytes(responseData["storagemax"])
                    storageProgressThing.value = responseData["storageused"]
                    storageProgressThing.max = responseData["storagemax"]
                    noteCount = responseData["notecount"]
                    localStorage.setItem("CACHE-username", responseData["username"])
                }
            }
            doStuff()
        });
}
usernameBox.addEventListener("click", () => {
    optionsCoverDiv.classList.remove("hidden")
    optionsDiv.classList.remove("hidden")
    updateUserInfo()
});
logOutButton.addEventListener("click", () => {
    window.location.replace("/logout")
});
exitThing.addEventListener("click", () => {
    optionsDiv.classList.add("hidden")
    optionsCoverDiv.classList.add("hidden")
});
deleteMyAccountButton.addEventListener("click", () => {
    if (confirm("Are you REALLY sure that you want to delete your account? There's no going back!") === true) {
        fetch(remote + "/api/deleteaccount", {
            method: "POST",
            body: JSON.stringify({
                secretKey: secretkey
            }),
            headers: {
                "Content-Type": "application/json; charset=UTF-8"
            }
        })
            .then((response) => {
                if (response.status === 200) {
                    window.location.href = "/logout"
                } else {
                    displayError("Failed to delete account (HTTP error code " + response.status + ")")
                }
            })
    }
});
importNotesButton.addEventListener("click", () => {
    optionsDiv.classList.add("hidden")
    importNotesDiv.classList.remove("hidden")
});
sessionManagerButton.addEventListener("click", () => {
    optionsDiv.classList.add("hidden")
    sessionManagerDiv.classList.remove("hidden")

    fetch(remote + "/api/sessions/list", {
        method: "POST",
        body: JSON.stringify({
            secretKey: secretkey
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
        .then((response) => {
            async function doStuff() {
                let responseData = await response.json()
                document.querySelectorAll(".burgerSession").forEach((el) => el.remove());
                let ua;
                for (let i in responseData) {
                    let sessionElement = document.createElement("div")
                    let sessionText = document.createElement("p")
                    let sessionImage = document.createElement("img")
                    let sessionRemoveButton = document.createElement("button")
                    sessionText.classList.add("w300")
                    if (responseData[i]["thisSession"] === true) {
                        sessionText.innerText = "(current) " + responseData[i]["device"]
                    } else {
                        sessionText.innerText = responseData[i]["device"]
                    }
                    sessionText.title = responseData[i]["device"]
                    sessionRemoveButton.innerText = "x"

                    sessionImage.src = "/static/svg/device_other.svg"

                    ua = responseData[i]["device"]

                    if (ua.includes("NT") || ua.includes("Linux")) {
                        sessionImage.src = "/static/svg/device_computer.svg"
                    }
                    if (ua.includes("iPhone" || ua.includes("Android") || ua.includes("iPod"))) {
                        sessionImage.src = "/static/svg/device_smartphone.svg"
                    }

                    sessionRemoveButton.addEventListener("click", () => {
                        fetch(remote + "/api/sessions/remove", {
                            method: "POST",
                            body: JSON.stringify({
                                secretKey: secretkey,
                                sessionId: responseData[i]["id"]
                            }),
                            headers: {
                                "Content-Type": "application/json; charset=UTF-8"
                            }
                        })
                            .then(() => {
                                if (responseData[i]["thisSession"] === true) {
                                    window.location.replace("/logout")
                                }
                            });
                        sessionElement.remove()
                    });

                    sessionElement.append(sessionImage)
                    sessionElement.append(sessionText)
                    sessionElement.append(sessionRemoveButton)

                    sessionElement.classList.add("burgerSession")

                    sessionDiv.append(sessionElement)
                }
            }
            doStuff()
        });
});
exitImportThing.addEventListener("click", () => {
    optionsDiv.classList.remove("hidden")
    importNotesDiv.classList.add("hidden")
});
exitSessionsThing.addEventListener("click", () => {
    optionsDiv.classList.remove("hidden")
    sessionManagerDiv.classList.add("hidden")
});

function updateWordCount() {
    let wordCount = noteBox.value.split(" ").length
    if (wordCount === 1) {
        wordCount = 0
    }
    wordCountBox.innerText = wordCount + " words"
}

function renderMarkDown() {
    if (markdowntoggle) {
        markdown.srcdoc = "<!DOCTYPE html><html lang='en'><style>html { height: 100% } pre { white-space: pre-wrap; overflow-wrap: break-word; } body { white-space: pre-wrap; overflow-wrap: break-word; font-family: 'Inter', sans-serif; height: 100%; color: " + getComputedStyle(document.documentElement).getPropertyValue('--text-color') + "; font-size: " + currentFontSize + "px; }</style>" + marked.parse(noteBox.value) + "</html>"
    }
}

function selectNote(nameithink) {
    document.querySelectorAll(".noteButton").forEach((el) => el.classList.remove("selected"));
    let thingArray = Array.from(document.querySelectorAll(".noteButton")).find(el => String(nameithink) === String(el.id));
    thingArray.classList.add("selected")

    fetch(remote + "/api/readnote", {
        method: "POST",
        body: JSON.stringify({
            secretKey: secretkey,
            noteId: nameithink,
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
        .catch(() => {
            noteBox.readOnly = true
            noteBox.value = ""
            noteBox.placeholder = ""
            displayError("Something went wrong... Please try again later!")
        })
        .then((response) => {
            selectedNote = nameithink
            if (mobile) {
                handleGesture()
            }
            noteBox.readOnly = false
            noteBox.placeholder = "Type something!"

            async function doStuff() {
                let responseData = await response.json()

                let bytes = CryptoJS.AES.decrypt(responseData["content"], password);
                noteBox.value = bytes.toString(CryptoJS.enc.Utf8)
                updateWordCount()
                renderMarkDown()

                noteBox.addEventListener("input", () => {
                    updateWordCount()
                    renderMarkDown()
                    clearTimeout(timer);
                    timer = setTimeout(() => {
                        let encryptedTitle = "New note"
                        if (noteBox.value.substring(0, noteBox.value.indexOf("\n")) !== "") {
                            let firstTitle = noteBox.value.substring(0, noteBox.value.indexOf("\n"));

                            document.getElementById(nameithink).innerText = firstTitle
                            encryptedTitle = CryptoJS.AES.encrypt(firstTitle, password).toString();
                        }
                        let encryptedText = CryptoJS.AES.encrypt(noteBox.value, password).toString();

                        if (selectedNote === nameithink) {
                            fetch(remote + "/api/editnote", {
                                method: "POST",
                                body: JSON.stringify({
                                    secretKey: secretkey,
                                    noteId: nameithink,
                                    content: encryptedText,
                                    title: encryptedTitle
                                }),
                                headers: {
                                    "Content-Type": "application/json; charset=UTF-8"
                                }
                            })
                                .then((response) => {
                                    if (response.status === 418) {
                                        displayError("You've ran out of storage... Changes will not be saved until you free up storage!")
                                    }
                                })
                                .catch(() => {
                                    displayError("Failed to save changes, please try again later...")
                                })
                        }
                    }, waitTime);
                });
            }
            doStuff()
        });
}

function updateNotes() {
    fetch(remote + "/api/listnotes", {
        method: "POST",
        body: JSON.stringify({
            secretKey: secretkey
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
        .then((response) => {
            async function doStuff() {
                document.querySelectorAll(".noteButton").forEach((el) => el.remove());
                noteBox.readOnly = true
                selectedNote = 0
                noteBox.placeholder = ""
                noteBox.value = ""
                clearTimeout(timer)
                updateWordCount()
                renderMarkDown()

                let responseData = await response.json()
                for (let i in responseData) {
                    let noteButton = document.createElement("button");
                    noteButton.classList.add("noteButton")
                    notesDiv.append(noteButton)

                    let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password);
                    let originalTitle = bytes.toString(CryptoJS.enc.Utf8);

                    noteButton.id = responseData[i]["id"]
                    noteButton.innerText = truncateString(originalTitle, 15)

                    noteButton.addEventListener("click", (event) => {
                        if (event.ctrlKey) {
                            fetch(remote + "/api/removenote", {
                                method: "POST",
                                body: JSON.stringify({
                                    secretKey: secretkey,
                                    noteId: responseData[i]["id"]
                                }),
                                headers: {
                                    "Content-Type": "application/json; charset=UTF-8"
                                }
                            })
                                .then(() => {
                                    updateNotes()
                                })
                                .catch(() => {
                                    displayError("Something went wrong! Please try again later...")
                                })
                        } else {
                            selectNote(responseData[i]["id"])
                        }
                    });
                }
                document.querySelectorAll(".loadingStuff").forEach((el) => el.remove());
            }
            doStuff()
        });
}

updateNotes()

newNote.addEventListener("click", () => {
    let noteName = "New note"
    let encryptedName = CryptoJS.AES.encrypt(noteName, password).toString(CryptoJS.enc.Utf8);
    fetch(remote + "/api/newnote", {
        method: "POST",
        body: JSON.stringify({
            secretKey: secretkey,
            noteName: encryptedName,
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
        .catch(() => {
            displayError("Failed to create new note, please try again later...")
        })
        .then((response) => {
            if (response.status !== 200) {
                updateNotes()
                displayError("Failed to create new note (HTTP error code " + response.status + ")")
            } else {
                updateNotes()
            }
        });
});
function downloadObjectAsJson(exportObj, exportName) {
    let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
    let downloadAnchorNode = document.createElement("a");
    downloadAnchorNode.setAttribute("href", dataStr);
    downloadAnchorNode.setAttribute("download", exportName + ".json");
    document.body.appendChild(downloadAnchorNode);
    downloadAnchorNode.click();
    downloadAnchorNode.remove();
}

function exportNotes() {
    fetch(remote + "/api/exportnotes", {
        method: "POST",
        body: JSON.stringify({
            secretKey: secretkey
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
        .then((response) => {
            async function doStuff() {
                let responseData = await response.json()
                for (let i in responseData) {
                    exportNotes.innerText = "Decrypting " + i + "/" + noteCount

                    let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password);
                    responseData[i]["title"] = bytes.toString(CryptoJS.enc.Utf8)

                    let bytesd = CryptoJS.AES.decrypt(responseData[i]["content"], password);
                    responseData[i]["content"] = bytesd.toString(CryptoJS.enc.Utf8)
                }
                let jsonString = JSON.parse(JSON.stringify(responseData))
                downloadObjectAsJson(jsonString, "data")
                optionsDiv.classList.add("hidden")
                displayError("Exported notes!")
            }
            doStuff()
        })
}

function importNotes(plaintextNotes) {
    for (let i in plaintextNotes) {
        let originalTitle = plaintextNotes[i]["title"];
        let encryptedTitle = CryptoJS.AES.encrypt(originalTitle, password).toString();
        plaintextNotes[i]["title"] = encryptedTitle;

        let originalContent = plaintextNotes[i]["content"];
        let encryptedContent = CryptoJS.AES.encrypt(originalContent, password).toString();
        plaintextNotes[i]["content"] = encryptedContent;
    }
    fetch(remote + "/api/importnotes", {
        method: "POST",
        body: JSON.stringify({
            "secretKey": localStorage.getItem("DONOTSHARE-secretkey"),
            "notes": JSON.stringify(plaintextNotes)
        }),
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        }
    })
    .then((response) => {
        async function doStuff() {
            if (response.status === 500) {
                optionsDiv.classList.add("hidden")
                importNotesDiv.classList.add("hidden")
                displayError("Something went wrong! Perhaps your note file was invalid?")
            } else {
                optionsDiv.classList.add("hidden")
                importNotesDiv.classList.add("hidden")
                displayError("Notes uploaded!")
                updateNotes()
            }
        }
        doStuff()
    })
}

function firstNewVersion() {
    if (localStorage.getItem("NEWVERSION") === "1.2") {
        return false;
    } else {
        localStorage.setItem("NEWVERSION", "1.2")
        return true;
    }
}

function toggleMarkdown() {
    if (markdown.style.display === 'none') {
        enableMarkdown()
    } else {
        disableMarkdown()
    }
}

function enableMarkdown() {
    markdown.style.display = 'inherit';
    markdowntoggle = true
    renderMarkDown()
}

function disableMarkdown() {
    markdown.style.display = 'none';
    markdowntoggle = false
    markdown.srcdoc = ""
}

exportNotesButton.addEventListener("click", () => {
    exportNotes()
});

importFile.addEventListener('change', function(e) {
    let fileread = new FileReader()
    fileread.addEventListener(
        "load",
        () => {
            let decrypted = JSON.parse(fileread.result)
            importNotes(decrypted)
        },
        false,
    );

    fileread.readAsText(importFile.files[0])
})

removeBox.addEventListener("click", () => {
    if (selectedNote === 0) {
        displayError("You need to select a note first!")
    } else {
        fetch(remote + "/api/removenote", {
            method: "POST",
            body: JSON.stringify({
                secretKey: secretkey,
                noteId: selectedNote
            }),
            headers: {
                "Content-Type": "application/json; charset=UTF-8"
            }
        })
            .then(() => {
                updateNotes()
            })
            .catch(() => {
                displayError("Something went wrong! Please try again later...")
            })
    }
});

document.addEventListener("DOMContentLoaded", function() {
    markdown.srcdoc = "<!DOCTYPE html><html lang='en'><style>html { height: 100% } pre { white-space: pre-wrap; overflow-wrap: break-word; } body { white-space: pre-wrap; overflow-wrap: break-word; font-family: 'Inter', sans-serif; height: 100%; color: " + getComputedStyle(document.documentElement).getPropertyValue('--text-color') + "; font-size: " + currentFontSize + "px; }</style>" + marked.parse(noteBox.value) + "</html>"
});

if (firstNewVersion()) {
    displayError("What's new in Burgernotes 2.0?\nRestyled client\nAdded changing passwords\nMigrated to OAuth2\nAdded importing notes")
}

checknetwork()
