/*
    Created: 2025-11-25
    Author: Kārlis Grīnvalds
    Last edited: 2025-11-25
    Edited by: Kārlis Grīnvalds
*/

// Used for loading content on viewing pages

function LoadContent(content) {
    let value = RemoveHTML(content).split("\n");
    let html = [];
    let str = "";
    let creatingList = false;
    for (let _ = 0; _ < value.length; _++) {
        const trimChar = value[_].trim();
        let notAdded = false;
        // Finished creating the list
        if (trimChar[0] != "*" && creatingList) {
            creatingList = false;
            str = str.replaceAll("</ul><ul>", "");
            html.push(str);
            str = "";
        }
        switch (trimChar[0]) {
            // Headings
            case "#":
                const headingSplit = value[_].split("# ");
                let headingType = headingSplit[0].trim().length + 2;
                let headingText = headingSplit[1];
                if (headingSplit[1] != undefined) {
                    if (headingType < 7) {
                        html.push(`<h${headingType} id="${headingText}">${headingText}</h${headingType}><hr>`);
                        break;
                    }
                }
                notAdded = true;
                break;
            // Unordered list
            case ">":
                const listSplit = value[_].split("> ");
                if (!listSplit[0].trim().split('').every(char => char === ">")) {
                    notAdded = true;
                    break;
                }
                let listIndent = listSplit[0].trim().length + 1;
                if (listSplit[1] == undefined) {
                    notAdded = true;
                    break;
                }
                creatingList = true;
                str += "<ul>";
                for (let _index = 1; _index < listIndent; _index++) {
                    str += "<ul>";
                }
                str += "<li>" + listSplit[1] + "</li>";
                for (let _index = 0; _index < listIndent; _index++) {
                    str += "</ul>";
                }
                break;
            // Table start - <table>
            case "{":
                if (value[_][1] == "|" && value[_].length == 2) {
                    html.push("<table>");
                    break;
                }
                if (value[_][1] == "|" && value[_][2] == " ") {
                    let tableSplit = value[_].split("content-list");
                    if (tableSplit.length == 2) {
                        html.push("<table class=\"content-list\"><tr><th>Content</th></tr><tr><td id=\"ContentList\"></td></tr></table>");
                        break;
                    }
                    else {
                        tableSplit = value[_].split(" style=\"");
                        let tableStyle = "";
                        let tableClasses = "";
                        if (tableSplit.length == 2) {
                            tableStyle = tableSplit[1].split("\"")[0];
                        }
                        tableSplit = value[_].split("borders");
                        if (tableSplit.length == 2) {
                            tableClasses = "borders";
                        }
                        html.push("<table style=\"" + tableStyle + "\" class=\"" + tableClasses + "\">");
                        break;
                    }
                }
                notAdded = true;
                break;
            // Table end, cells, rows - </table> <td> <tr>
            case "|":
                if (value[_][1] == "}" && value[_].length == 2) {
                    html.push("</tr></table>");
                    break;
                }
                if (value[_][1] == "|") {
                    const splitCell = value[_].split("|| ");
                    if (splitCell.length == 2) {
                        html.push("<td>" + splitCell[1] + "");
                        break;
                    }
                }
                if (value[_][1] == "-" && value[_].length == 2) {
                    html.push("<tr>");
                    break;
                }
                notAdded = true;
                break;
            // Table headers
            case "!":
                const splitHeader = value[_].split("!! ");
                if (splitHeader.length == 2) {
                    let headerValues = splitHeader[1].split("} ");
                    if (headerValues.length == 2) {
                        html.push("<th style=\"width: " + headerValues[0].substring(1, headerValues[0].length).split(";")[0] + "\">" + headerValues[1] + "</th>");
                    }
                    else {
                        html.push("<th>" + splitHeader[1] + "</th>");
                    }
                }
                else {
                    notAdded = true;
                }
                break;
            // Paragraph
            default:
                html.push("<p>" + value[_] + "</p>");
                break;
        }
        // Finished creating the list
        if (_ + 1 == value.length && creatingList) {
            creatingList = false;
            str = str.replaceAll("</ul><ul>", "");
            html.push(str);
            str = "";
        }
        // If the value wasn't added, then it gets added as a paragraph
        if (notAdded && !creatingList) {
            html.push("<p>" + value[_] + "</p>");
            creatingList = false;
            str = "";
        }
    }
    return html;
}

function CreateContentList(html) {
    if ($("#ContentList").length == 1) {
        let theList = "<ol>";
        let previousIndent = 1;
        for (let _ = 0; _ < html.length; _++) {
            let indent = html[_][2];
            if (html[_].endsWith("</h" + indent + ">") || html[_].endsWith("</h" + indent + "><hr>")) {
                let innerValue = html[_].split("\">")[1].split("</h" + indent + ">")[0];
                indent--;
                if (previousIndent > indent) {
                    for (let _index = previousIndent; _index > indent; _index--) {
                        theList += "</ol>";
                    }
                }
                else {
                    for (let _index = previousIndent; _index < indent; _index++) {
                        theList += "<ol>";
                    }
                }
                if (_ != 0) {
                    theList += "</li>";
                }
                theList += "<li><a href=\"#" + innerValue + "\">" + innerValue + "</a>";
                previousIndent = indent;
            }
        }
        theList += "</ol>";
        $("#ContentList").append(theList);
    }
}

// Function returns formatted text that has converted special characters into HTML tags
function FormatText(html) {
    let completeHTML = "";
    // Replaces ``` with <pre>
    html = ConvertToPreformatted(html);
    for (let _ = 0; _ < html.length; _++) {
        let preparedText = html[_];
        if (!html[_].startsWith("<pre>")) {
            // Bold
            preparedText = ReplaceSymbols(preparedText, "**");
            // Italic
            preparedText = ReplaceSymbols(preparedText, "''");
            // Underlined
            preparedText = ReplaceSymbols(preparedText, "__");
            // Crossed out
            preparedText = ReplaceSymbols(preparedText, "~~");
            // Redacted
            preparedText = ReplaceSymbols(preparedText, "==");
            // Styled
            preparedText = CreateStyledElement(preparedText);
            // Media
            preparedText = CreateMedia(preparedText);
        }
        completeHTML += preparedText;
    }
    return completeHTML.replaceAll("<p></p>", "<br>");
}

// Transforms ```text``` into <pre>text</pre> (preformatted text)
function ConvertToPreformatted(html) {
    let text = "";
    for (let _ = 0; _ < html.length; _++) {
        text += html[_] + "\n";
    }
    let splitText = text.split("```");
    let result = "";
    if (splitText.length > 2) {
        result = splitText[0];
        for (let _ = 1; _ < splitText.length; _ += 2) {
            if (_ + 2 > splitText.length) {
                result += "```" + splitText[_];
                result = result.split("\n");
                result.pop();
                return result;
            }
            if (!splitText[_ - 1].endsWith("\n<p>")) {
                result += "</p>\n";
            }
            else {
                result = result.substring(0, result.length - 3);
            }
            result += "<pre>" + splitText[_].replaceAll("<p>", "<br>").replaceAll("</p>", "").replaceAll("\n", "");
            if (splitText[_ + 1].startsWith("</p>\n")) {
                result += "</pre>" + splitText[_ + 1].replace("</p>\n", "\n");
            }
            else {
                result += "</pre>\n<p>" + splitText[_ + 1];
            }
        }
        result = result.split("\n");
        result.pop();
        return result;
    }
    else {
        return html;
    }
}

// Function returns text line with HTML tags
function ReplaceSymbols(text, tag) {
    let result = "";
    let splitText = text.split(tag);
    let tagName = "p";
    // Selects html tag
    switch (tag) {
        case "**":
            tagName = "b";
            break;
        case "''":
            tagName = "i";
            break;
        case "__":
            tagName = "u";
            break;
        case "~~":
            tagName = "del";
            break;
        case "==":
            tagName = "span";
            break;
    }
    // Replaces special characters with html tags
    for (let _ = 1; _ < splitText.length; _ += 2) {
        if (_ == 1) {
            result += splitText[0];
        }
        if (splitText[_ + 1] != undefined) {
            if (tag == "==") {
                // For redacted
                let giveText = "";
                for (let _index = 0; _index < splitText[_].length; _index++) {
                    giveText += "█";
                }
                result += `<${tagName}>${giveText}</${tagName}>${splitText[_ + 1]}`;
            }
            else {
                result += `<${tagName}>${splitText[_]}</${tagName}>${splitText[_ + 1]}`;
            }
        }
        else {
            result += tag + splitText[_];
        }
    }
    // If nothing was changed, then returns unchanged text
    if (result == "") {
        return text;
    }
    return result;
}

// Creates an element with style attached to it
function CreateStyledElement(givenText) {
    // Creates an array from all words in the givenText
    let text = givenText.split("{{");
    let words = [];
    for (let _ = 1; _ < text.length; _++) {
        text[_] = "{{" + text[_];
    }
    words.push(text[0]);
    for (let _ = 1; _ < text.length; _++) {
        let splitText = text[_].split("}}");
        words.push(splitText[0] + "}}");
        words.push(splitText[1]);
    }
    // Replaces special characters with HTML tags and add attributes to them
    let html = "";
    for (let _ = 0; _ < words.length; _++) {
        if (words[_][0] + words[_][1] == "{{") {
            const splitMedia = words[_].substring(2, words[_].length - 2);
            if (splitMedia[0] != "{" && splitMedia[splitMedia.length - 1] != "}" && splitMedia.length > 0) {
                try {
                    const values = splitMedia.split("|");
                    let mediaURL = values[0].split("\"");
                    // Gives text and style inputted values
                    let style = values[0].split("style=\"")[1];
                    let text = values[1].split("text=\"")[1];
                    html += "<span style=\"" + style.split("\"")[0] + "\">" + text.split("\"")[0] + "</span>";
                    continue;
                }
                catch {
                    // If it fails and catches an error, then return unmodified word
                    html += words[_];
                    continue;
                }
            }
            else {
                // If there is, then return unmodified word
                html += words[_];
                continue;
            }
        }
        else {
            // Inserts the word without any modifications made to it, if it doesn't start with special characters
            html += words[_];
            continue;
        }
    }
    // Returns string with HTML elements
    return html;
}

// Generates link, image or audio HTML tag
function CreateMedia(givenText) {
    // Creates an array from all words in the givenText
    let text = givenText.split("[[");
    let words = [];
    for (let _ = 1; _ < text.length; _++) {
        text[_] = "[[" + text[_];
    }
    words.push(text[0]);
    for (let _ = 1; _ < text.length; _++) {
        let splitText = text[_].split("]]");
        words.push(splitText[0] + "]]");
        words.push(splitText[1]);
    }
    // Replaces special characters with HTML tags and add attributes to them
    let html = "";
    for (let _ = 0; _ < words.length; _++) {
        // Transforms the word into a link or a media, if features special characters
        if (words[_][0] + words[_][1] == "[[") {
            // Removes [] from the word
            const splitMedia = words[_].substring(2, words[_].length - 2);
            // Checks if there are any [] left
            if (splitMedia[0] != "[" && splitMedia[splitMedia.length - 1] != "]" && splitMedia.length > 0) {
                // Tries to create the <a>, <img> or <audio>
                try {
                    // Splits all media values
                    const values = splitMedia.split("|");
                    let mediaURL = values[0].split("\"");
                    // Gets the media type
                    let mediaType = "";
                    if (mediaURL[0] == "file=") {
                        mediaType = "file";
                    }
                    else if (mediaURL[0] == "link=") {
                        mediaType = "link";
                    }
                    else {
                        html += words[_];
                        continue;
                    }
                    // Creates the url or src
                    mediaURL = mediaURL[1];
                    // Gives text and style inputted values
                    let mediaText = "";
                    let mediaStyle = "";
                    for (let _index = 1; _index < 3; _index++) {
                        let selectValue = values[_index];
                        if (selectValue != undefined) {
                            let check = selectValue.split("\"")[0];
                            if (check == "text=") {
                                selectValue = selectValue.split("text=\"")[1];
                                selectValue = selectValue.split("\"")[0];
                                if (mediaType == "file") {
                                    mediaText = (selectValue.length > 0) ? selectValue : "";
                                }
                                else {
                                    mediaText = (selectValue.length > 0) ? selectValue : mediaURL;
                                }
                            }
                            if (check == "style=") {
                                selectValue = selectValue.split("style=\"")[1];
                                selectValue = selectValue.split("\"")[0];
                                mediaStyle = (selectValue.length > 0) ? selectValue : "";
                            }
                        }
                        else {
                            mediaText = (mediaText.length > 0) ? mediaText : mediaURL;
                        }
                    }
                    // Checks if there is any style to add
                    let addStyle = (mediaStyle.length > 0) ? "style=\"" + mediaStyle + "\"" : "";
                    if (mediaType == "file") {
                        // Checks the file type
                        let arr = mediaURL.split(".");
                        let fileType = arr[arr.length - 1];
                        if (fileType == "mp3" ||fileType == "wav") {
                            // Attaches the audio <audio></audio> to HTML as string
                            html += "<div>" + mediaText + "<br><audio " + addStyle + " controls><source src=\"/" + Topic() + "/load/" + mediaURL + "\"></audio></div>";
                            continue;
                        }
                        else {
                            // Attaches the image <img> to HTML as string
                            html += "<div><a href=\"load/" + mediaURL + "\"><img src=\"/" + Topic() + "/load/" + mediaURL + "\" " + addStyle + "></a><br>" + mediaText + "</div>";
                            continue;
                        }
                    }
                    else {
                        // Attaches the link <a></a> to HTML as string
                        html += "<a href=\"" + mediaURL + "\" " + addStyle + ">" + mediaText + "</a>";
                        continue;
                    }
                }
                catch {
                    // If it fails and catches an error, then return unmodified word
                    html += words[_];
                    continue;
                }
            }
            else {
                // If there is, then return unmodified word
                html += words[_];
                continue;
            }
        }
        else {
            // Inserts the word without any modifications made to it, if it doesn't start with special characters
            html += words[_];
            continue;
        }
    }
    // Returns string with HTML elements
    return html;
}

// Removes all HTML tags from the inputted string
function RemoveHTML(HTMLString) {
    const parser = new DOMParser();
    const doc = parser.parseFromString(HTMLString, "text/html");
    const textContent = doc.body.textContent || "";
    return textContent;
}