let UserInfo = {};
let PageIntervals = [];
let config =
    {
        articleRefresh: 300000,
        messageFadeIn: 300,
        messageDisappear: 200
    };

function isLoggedIn() {
    "use strict";
    return UserInfo.Email && UserInfo.Email.length > 0;
}

async function setElementClasses(element, newClasses) {
    // Ensure the element exists
    if (!element) return;

    // Clear all existing classes
    element.className = '';

    // Add the new classes to the element
    element.classList.add(...newClasses);
}

async function handleResponse(data, successMessage, failureMessage) {
    "use strict";
    const statusMessageContainer = document.getElementById("statusMessageContainer");

    const statusMessage = document.createElement("div");
    statusMessage.classList.add("status-message");

    if (data.Status === 'Success') {
        statusMessage.innerText = successMessage;
        statusMessage.classList.add("success");
    } else {
        statusMessage.innerText = failureMessage;
        statusMessage.classList.add("failure");
    }

    statusMessageContainer.appendChild(statusMessage);

    // Automatically remove the message after 3 seconds
    setTimeout(() => {
        statusMessage.style.opacity = "0";
        setTimeout(() => {
            statusMessage.remove();
        }, config.messageFadeIn);
    }, config.messageDisappear);
}

async function showDashboardGreeting() {
    "use strict";
    document.getElementById("welcomeMsg").innerText = `Ahoj, ${UserInfo.FirstName}.`;
}

async function doAction(url, requestData, successMessage, failureMessage, silent) {
    "use strict";
    const params = new FormData();

    for (const key in requestData) {
        params.append(key, requestData[key]);
    }

    const response = await fetch(url, {
        method: 'POST',
        body: params,
    });

    if (!response.ok) {
        console.error(`HTTP error! Status: ${response.status}`);
    }

    const data = await response.json();

    if (!silent) {
        await handleResponse(data, successMessage, failureMessage);
    }

    return data;
}


async function doSlicks() {
    const elements = document.getElementsByClassName('sliderm');
    Array.prototype.forEach.call(elements, function (element) {
        // Initialize the Slick carousel on each element
        const sliderm = new Sliderm('#' + element.id, {
            arrow: true,
            pagination: true,
            grouping: false,
            loop: true,
            preview: false,
            columns: 1,
            duration: 1000,
            spacing: 10,
            align: 'center',
        });
    });
}

async function handlePageResponse(data) {
    "use strict";
    const navbar = document.getElementById("navbar_container");
    const pageArea = document.getElementById("page_container");

    if (data.Navigation) {
        navbar.innerHTML = data.Navigation;
    }
    if (data.PageTitle) {
        document.title = data.PageTitle;
    }
    if (data.Page) {
        pageArea.innerHTML = data.Page;
        if (data.PageLocation) {
            history.pushState({}, "", data.PageLocation);
        }
    }
}

async function displayList(data, elementId, deleteFunction) {
    "use strict";
    const tableContainer = document.getElementById(elementId);
    tableContainer.innerHTML = ""; // Clear previous content

    const table = document.createElement("table");
    table.classList.add("list-table");

    const headerRow = table.insertRow(0);
    for (const key in data[0]) {
        const th = document.createElement("th");
        th.appendChild(document.createTextNode(key));
        headerRow.appendChild(th);
    }

    if (typeof deleteFunction === "function") {
        const th = document.createElement("th");
        let deleteBtn = document.createElement('i');
        deleteBtn.classList.add("ri-delete-bin-line");
        th.appendChild(deleteBtn);
        headerRow.appendChild(th);
    }

    for (const line of data) {
        const dataRow = table.insertRow();
        for (const key in line) {
            const td = document.createElement("td");
            td.appendChild(document.createTextNode(line[key]));
            dataRow.appendChild(td);
        }
        if (typeof deleteFunction === "function") {
            const td = document.createElement("td");
            const deleteButton = document.createElement('button');
            deleteButton.innerHTML = "<i class='ri-delete-bin-line'></i>";
            deleteButton.onclick = () => deleteFunction(line.ID);
            td.appendChild(deleteButton);
            dataRow.appendChild(td);
        }
    }

    tableContainer.appendChild(table);
}

async function doPageAction(requestData) {
    "use strict";
    const response = await fetch('/page', {
        method: 'POST',
        body: new URLSearchParams(requestData),
    });

    if (!response.ok) {
        console.error(`HTTP error! Status: ${response.status}`);
    }

    const data = await response.json();
    await handlePageResponse(data);
    return data;
}

async function initAjaxNavigationEvents() {
    "use strict";
    const allLinks = document.querySelectorAll('.navsite_link, .navpage_link');
    const pageLinks = document.querySelectorAll('.navpage_link');

    pageLinks.forEach(function (link) {
        link.addEventListener('click', function () {
            navLinks.classList.remove("active");
        });
    });

    allLinks.forEach(function (link) {
        link.addEventListener('click', function (e) {
            e.preventDefault();
            let site = this.dataset.site;
            let page = this.dataset.page;
            if (site && page) {
                navigateTo(site, page);
            }
        });
    });
    const toggleButton = document.getElementById("toggle_button");
    const navLinks = document.getElementById("navsite_list");

    toggleButton.addEventListener('click', () => {
        navLinks.classList.toggle("active");
    });
}

async function initAjax() {
    "use strict";

    await initAjaxNavigationEvents();
    await onPageLoad();
}

async function togglearticlecreate() {
    "use strict";
    let articleContainerElement = document.getElementById("articlecreatecontainer");

    articleContainerElement.classList.toggle("hidden");
}

async function togglememecreate() {
    "use strict";
    let memeContainerElement = document.getElementById("memecreatecontainer");

    await getMemeImages();
    memeContainerElement.classList.toggle("hidden");
}

async function renderarticles() {
    "use strict";
    let template = document.querySelector('template[data-template-name="article"]').innerHTML;
    let articles = await doAction(
        "/newsarticle",
        {
            action: "getNewsArticles"
        },
        "Články načítané",
        "Nastala chyba pri načítavaní článkov",
        true
    );

    let articleout = "";
    for (const article of articles.Articles) {
        articleout += template.replace("__TEMPLATE_ARTICLE_TITLE__", article.Title).replace("__TEMPLATE_ARTICLE_AUTHOR__", article.WrittenByName).replace("__TEMPLATE_ARTICLE_DATE__", article.WrittenAt).replace("__TEMPLATE_ARTICLE_BODY__", article.Body);
    }
    document.getElementById("articleslist").innerHTML = articleout;
}

async function submitarticle() {
    "use strict";
    let articleTitleElement = document.getElementById("articletitleinput");
    let articleBodyElement = document.getElementById("articlebodyinput");
    await doAction(
        "/newsarticle",
        {
            action: "addNewsArticle",
            title: articleTitleElement.value,
            body: articleBodyElement.value
        },
        "Článok úspešne pridaný",
        "Nastala chyba pri pridávaní článku",
        false
    );
    await togglearticlecreate();
}

async function articleInit() {
    "use strict";
    let articleContainerElement = document.getElementById("articlecreatecontainer");
    let articleCreateOpenElement = document.getElementById("articlecreateopen");
    articleContainerElement.addEventListener("keyup", function (ev) {
        if (ev.key === "Escape") {
            togglearticlecreate();
        }
    });
    PageIntervals.push(setInterval(renderarticles, config.articleRefresh));
    document.getElementById("articleprivilegeinput").setAttribute("max", UserInfo.Privileges);
    if (UserInfo.Privileges < 2) {
        articleContainerElement.style.display = "none";
        articleCreateOpenElement.style.display = "none";
    } else {
        articleCreateOpenElement.style.display = "inline-block";
    }
}

async function onPageLoad() {
    "use strict";
    await restoreUserInfo();
    let currentSite = localStorage.getItem("currentSite");
    let currentPage = localStorage.getItem("currentPage");

    for (let interval of PageIntervals) {
        clearInterval(interval);
    }

    if (currentSite === "account" && currentPage === "settings") {
        if (document.getElementById("user-settings")) {
            await populateUserInfoFields(UserInfo);
        }
        if (document.getElementById("admin-settings")) {
            await listActivationCodes(true);
            await listUsers(true);
        }
    }
    if (currentSite === "account" && currentPage === "index" && isLoggedIn()) {
        await showDashboardGreeting();
    }
    if (currentSite === "news" && currentPage === "index") {
        await articleInit();
    }
    if (currentSite === "account" && currentPage === "files") {
        await listFiles();
    }
    if (currentSite === "memes" && currentPage === "index") {
        await getMemeImages();
    }
    await doSlicks();
}

async function navigateTo(site, page) {
    "use strict";
    const data = {
        action: "getPage",
        site: site,
        page: page,
    };
    doPageAction(data).then(() => {
        localStorage.setItem("currentSite", site);
        localStorage.setItem("currentPage", page);
        onPageLoad();
    });
}

async function softReload() {
    "use strict";
    let currentSite = localStorage.getItem("currentSite");
    let currentPage = localStorage.getItem("currentPage");
    await navigateTo(currentSite, currentPage);
    umami.track("softReload");
}

async function refreshNavbar() {
    "use strict";
    const data = {
        action: "getNavigation",
    };
    await doPageAction(data);
    umami.track("refreshNavbar");
    await initAjaxNavigationEvents();
}

async function logout() {
    "use strict";
    const data = {
        action: "logout",
    };

    doAction('/account', data, "Logout Successful!", "Logout failed.", false)
        .then(async () => {
            await refreshNavbar();
            await navigateTo(localStorage.getItem("defaultSite"), localStorage.getItem("defaultPage"));
            localStorage.clear();
            UserInfo = {};
            umami.track("logout");
        })
        .catch((error) => {
            // Handle errors if needed
            console.error("An error occurred during logout:", error);
        });
}

async function login() {
    "use strict";
    const email = document.getElementById("login_email").value;
    const password = document.getElementById("login_password").value;
    await doLogin(email, password);
    await getUserInfo();
    await refreshNavbar();
    await softReload();
}

async function doLogin(email, password) {
    "use strict";
    const data = {
        action: "login",
        email: email,
        password: password,
    };

    await doAction('/account', data, "Login Successful!", "Login failed. Please check your credentials.", false);
    umami.track("login");
}

async function register() {
    "use strict";
    const firstName = document.getElementById("register_firstName").value;
    const lastName = document.getElementById("register_lastName").value;
    const email = document.getElementById("register_email").value;
    const password = document.getElementById("register_password").value;
    const activationToken = document.getElementById("register_activationToken").value;

    const data = {
        action: "register",
        firstname: firstName,
        lastname: lastName,
        email: email,
        password: password,
        activation_token: activationToken,
    };

    await doRegister(data);
}

async function doRegister(requestData) {
    "use strict";
    await doAction('/account', requestData, "Registration Successful!", "Registration failed.", false);
    umami.track("register");
}

//User settings start

async function changePassword() {
    "use strict";
    const oldPassword = document.getElementById("changeOldPassword").value;
    const newPassword = document.getElementById("changeNewPassword").value;

    const data = {
        action: "change_password",
        old_password: oldPassword,
        new_password: newPassword,
    };

    await doChangePassword(data, "Password change Successful!", "Password change failed.");
}

async function doChangePassword(requestData, successMessage, failureMessage) {
    "use strict";
    await doAction('/account', requestData, successMessage, failureMessage, false);
    umami.track("passwordChange");
}

async function updateUserProfile() {
    "use strict";
    const firstName = document.getElementById("updateFirstName").value;
    const lastName = document.getElementById("updateLastName").value;
    const nickname = document.getElementById("updateNickname").value;
    const minecraftNick = document.getElementById("updateMinecraftNick").value;

    const data = {
        action: "update_user_profile",
        first_name: firstName,
        last_name: lastName,
        nickname: nickname,
        minecraft_nick: minecraftNick,
    };

    await doAction('/account', data, "Profile update Successful!", "Profile update failed.", false);
    umami.track("updateUserProfile");
}

async function updateEmail() {
    "use strict";
    const newEmail = document.getElementById("updateNewEmail").value;

    const data = {
        action: "update_user_email",
        email: newEmail,
    };

    await doAction('/account', data, "Email update Successful!", "Email update failed.", false);
    umami.track("updateEmail");
}

async function populateUserInfoFields(userData) {
    "use strict";
    document.getElementById("updateFirstName").value = userData.FirstName || "";
    document.getElementById("updateLastName").value = userData.LastName || "";
    document.getElementById("updateNickname").value = userData.Nickname || "";
    document.getElementById("updateMinecraftNick").value = userData.MinecraftNick || "";
    document.getElementById("updateNewEmail").value = userData.Email || "";
}

async function restoreUserInfo() {
    "use strict";
    for (let i = 0; i < localStorage.length; i++) {
        let key = localStorage.key(i);
        if (key.startsWith("UserInfo_")) {
            let keyClean = key.replace("UserInfo_", "");
            UserInfo[keyClean] = localStorage.getItem(key);
        }
    }
}

async function getUserInfo() {
    "use strict";
    const data = {
        action: "get_user_info",
    };
    const result = await doAction('/account', data, "User info retrieved Successfully!", "User info retrieval failed.", true);

    if (result && result.Status === "Success") {
        Object.keys(result.UserInfo).forEach(index => {
            let value = result.UserInfo[index];
            localStorage.setItem("UserInfo_" + index, value);
            UserInfo[index] = value;
        });
    }

}

//User settings end

//Admin settings start

async function addActivationCodes() {
    "use strict";
    const count = document.getElementById("activationCodeCount").value;

    const data = {
        action: "add_activation_codes",
        count: count,
    };

    doAction('/account', data, "Activation codes added Successfully!", "Activation codes addition failed.", false).then((result) => {
        displayList(result.ActivationCodes, "codeListTable", deleteActivationCode);
        umami.track("addActivationCodes");
    });
}

async function listUsers(silent) {
    "use strict";
    const data = {
        action: "list_users",
    };

    doAction('/account', data, "User list retrieved Successfully!", "User list retrieval failed.", silent).then((result) => {

        if (result && result.Status === "Success") {
            displayList(result.Users, "userListTable", deleteUser);
        }
    });
}

async function listActivationCodes(silent) {
    "use strict";
    const data = {
        action: "list_activation_codes",
    };

    doAction('/account', data, "Activation code list retrieved Successfully!", "Activation code list retrieval failed.", silent).then((result) => {
        displayList(result.ActivationCodes, "codeListTable", deleteActivationCode);
    });
}

async function deleteUser(userId) {
    "use strict";
    const data = {
        action: "delete_user",
        user_id: userId,
    };

    await doAction('/account', data, "User deleted Successfully!", "User deletion failed.", false);
    await listUsers(false);
    umami.track("deleteUser");
}

async function deleteActivationCode(activationCode) {
    "use strict";
    const data = {
        action: "delete_activation_code",
        activation_code: activationCode,
    };

    await doAction('/account', data, "Activation code deleted Successfully!", "Activation code deletion failed.", false);
    await listActivationCodes(false);
    umami.track("deleteActivationCode");
}

//Admin settings end

if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", initAjax);
} else {
    setTimeout(initAjax, 0);
}

async function uploadFile() {
    const fileInput = document.getElementById('fileInput');
    const fileForm = document.getElementById('uploadForm');
    let data = {
        action: "uploadFiles"
    };
    for (let i = 0; i < fileInput.files.length; i++) {
        data[`userFile${i}`] = fileInput.files[i];
    }
    await doAction("/upload", data, "Súbor bol úspešne nahraný", "Nastala chyba pri nahrávaní súboru", false);
    fileForm.reset();
    await listFiles();
}

async function deleteFile(fileID) {
    await doAction("/upload", {
        action: "deleteFile",
        file_id: fileID
    }, "Súbor bol úspešne zmazaný", "Nastala chyba pri mazaní súboru", true);
    await listFiles();
}

async function getFileList() {
    const resp = await doAction("/upload", {
        action: "getAllFiles"
    }, "Zoznam súborov bol úspešne stiahnutý", "Nastala chyba pri sťahovaní zoznamu súborov", true);

    if (resp.Status === "Success") {
        return resp.Files;
    } else {
        return false;
    }
}

async function listFiles() {
    const fileList = await getFileList();
    if (fileList) {
        await displayList(fileList, "filelist", deleteFile);
    }
}

async function addMeme() {
    let memeTitleElement = document.getElementById("meme_title_input");
    let memeTextElement = document.getElementById("meme_text_input");
    let memeImageElement = document.getElementById("meme_image_input");

    await doAction("/meme", {
        action: "addMeme",
        meme_title: memeTitleElement.value,
        meme_text: memeTextElement.value,
        meme_image_id: memeImageElement.value
    }, "Meme bol zmazaný", "Nastala chyba pri mazaní meme-u", false);
    memeTitleElement.value = "";
    memeTextElement.value = "";
    memeImageElement.selectedIndex = 0;
    await togglememecreate();
}

async function deleteMeme(memeId) {
    await doAction("/meme", {
        action: "deleteMeme",
        meme_id: memeId
    }, "Meme bol zmazaný", "Nastala chyba pri mazaní meme-u", false);
    await softReload();
}

async function getMemeImages() {
    let memeImageSelector = document.getElementById("meme_image_input");
    let fileList = await getFileList();
    fileList.forEach((item) => {
        let option = document.createElement("option");
        option.value = item.ID;
        let splitPath = item.Path.split("/");
        option.text = `${splitPath[splitPath.length - 1]} - ID: (${item.ID}) Autor: [${item.UploadedBy} (${item.UploadedByID})]`;
        memeImageSelector.appendChild(option);
    });

}

async function reloadMemeVotes(memeID) {
    let memeVoteCounterElement = document.getElementById(`meme_votes_counter_${memeID}`);
    let memeVoteUpvoteElement = document.getElementById(`meme_votes_upvote_${memeID}`);
    let memeVoteDownvoteElement = document.getElementById(`meme_votes_downvote_${memeID}`);
    let memeVoteUpvoteButtonElement = document.getElementById(`meme_votes_upvote_button_${memeID}`);
    let memeVoteDownvoteButtonElement = document.getElementById(`meme_votes_downvote_button_${memeID}`);


    let memeVoteResponse = await doAction('/meme', {
        action: "getMemeVotes",
        meme_id: memeID
    }, "Počet hlasov k meme-u bol stiahnutý", "Nastala chyba pri sťahovaní počtu hlasov k meme-u", true);

    let memeVotes = memeVoteResponse.NetVotes;
    let userVote = memeVoteResponse.UserVote;
    memeVoteCounterElement.innerText = memeVotes;
    memeVoteCounterElement.classList.remove("positive", "negative", "neutral");

    if (0 < memeVotes) {
        memeVoteCounterElement.classList.add("positive");
    } else if (0 > memeVotes) {
        memeVoteCounterElement.classList.add("negative");
    } else {
        memeVoteCounterElement.classList.add("neutral");
    }

    memeVoteUpvoteButtonElement.classList.remove('visual_hover');
    memeVoteDownvoteButtonElement.classList.remove('visual_hover');
    let memeUpvoteVariant = "line";
    let memeDownvoteVariant = "line";
    if (0 < userVote) {
        memeUpvoteVariant = "fill";
        memeVoteUpvoteButtonElement.classList.add('visual_hover');
    } else if (0 > userVote) {
        memeDownvoteVariant = "fill";
        memeVoteDownvoteButtonElement.classList.add('visual_hover');
    }

    await setElementClasses(memeVoteUpvoteElement, [`ri-arrow-up-circle-${memeUpvoteVariant}`]);
    await setElementClasses(memeVoteDownvoteElement, [`ri-arrow-down-circle-${memeDownvoteVariant}`])

}

async function voteMeme(memeID, isUpvote) {
    let memeVoteUpvoteElement = document.getElementById(`meme_votes_upvote_${memeID}`);
    let memeVoteDownvoteElement = document.getElementById(`meme_votes_downvote_${memeID}`);
    let memeVoteDelete = false;
    if (isUpvote) {
        if (memeVoteUpvoteElement.classList.contains("ri-arrow-up-circle-fill")) {
            await deleteVoteMeme(memeID);
            memeVoteDelete = true;
        }
    } else {
        if (memeVoteDownvoteElement.classList.contains("ri-arrow-down-circle-fill")) {
            await deleteVoteMeme(memeID);
            memeVoteDelete = true;
        }
    }
    if (!memeVoteDelete) {
        await doAction("/meme", {
            action: "voteMeme",
            meme_id: memeID,
            is_upvote: isUpvote
        }, "Meme bol votovaný", "Nastala chyba pri votovaný", true);
    }
    await reloadMemeVotes(memeID);
}

async function deleteVoteMeme(memeId) {
    await doAction("/meme", {
        action: "deleteVoteMeme",
        meme_id: memeId
    }, "Hlas na meme bol zmazaný", "Nastala chyba pri mazaní hlasu na meme", true);
    await reloadMemeVotes(memeId);
}

async function surveySubmit() {
    const satisfaction = document.querySelector('input[name="satisfaction"]:checked');
    const functionality = document.querySelector('input[name="functionality"]:checked');
    const content = document.querySelector('input[name="content"]:checked');
    const comment = document.querySelector('textarea[name="comment"]');
    if (satisfaction && functionality && content && comment.value) {
        await doAction("/survey", {
            action: "surveySubmit",
            satisfaction: satisfaction.value,
            functionality: functionality.value,
            content: content.value,
            comment: comment.value
        }, "Zaznamenané",
            "Nastala chyba");
        satisfaction.checked = false;
        functionality.checked = false;
        content.checked = false;
        comment.value = "";
    }
}

async function toggleRegister() {
    let loginForm = document.getElementById("sign_in_form");
    let registerForm = document.getElementById("sign_up_form");
    loginForm.classList.toggle('hidden');
    registerForm.classList.toggle('hidden');
}