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

// Used for loading content on viewing pages

function LoadContent(content) {
    let value = content.replaceAll("&quot;", "\"").replaceAll("&#039;", "\'").split("\n");
    let html = [];
    let str = "";
    let creatingList = false;
    for (let _ = 0; _ < value.length; _++) {
        const trimChar = value[_];
        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 "#":
                let headingType = value[_].split("# ")[0].trim().length + 2;
                let headingText = value[_].substring(headingType, value[_].length);
                if (headingText.length > 0) {
                    if (headingType < 7) {
                        html.push(`<h${headingType}>${headingText}</h${headingType}><hr>`);
                        break;
                    }
                }
                notAdded = true;
                break;
            // Table start - <table>
            case "{":
                if (value[_][1] == "|" && value[_].trim().length == 2) {
                    html.push("<table>");
                    break;
                }
                if (value[_][1] == "|" && value[_][2] == " ") {
                    let tableSplit;
                    let tableStyle;
                    if (value[_].indexOf("side-content") != -1) {
                        // Creates a side table
                        tableSplit = value[_].split(" style=\"");
                        tableStyle = "";
                        if (tableSplit.length == 2) {
                            tableStyle = tableSplit[1].split("\"")[0];
                        }
                        html.push("<table class=\"side-content\" style=\"" + tableStyle + "\">");
                        break;
                    }
                    else if (value[_].indexOf("content-list") != -1) {
                        // Creates empty content table
                        html.push("<table class=\"content-list\"><tr><th>Content</th></tr><tr><td id=\"ContentList\"></td></tr></table>");
                        break;
                    }
                    else {
                        tableSplit = value[_].split(" style=\"");
                        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] == "|" && value[_][2] == " ") {
                    const cellValues = GetCellData(value[_].replace("|| ", ""));
                    html.push("</td><td style=\"" + cellValues.width + "\" rowspan=\"" + cellValues.rowspan + "\" colspan=\"" + cellValues.colspan + "\">" + cellValues.txt);
                    break;
                }
                if (value[_][1] == "-" && value[_].length == 2) {
                    html.push("<tr>");
                    break;
                }
                notAdded = true;
                break;
            // Table headers
            case "!":
                if (value[_].startsWith("!! ")) {
                    const headerValues = GetCellData(value[_].replace("!! ", ""));
                    html.push("</th><th style=\"width: " + headerValues.width + "\" rowspan=\"" + headerValues.rowspan + "\" colspan=\"" + headerValues.colspan + "\">" + headerValues.txt);
                }
                else {
                    notAdded = true;
                }
                break;
            // Comment and unordered list
            case "&":
                if (value[_].startsWith("&amp;&amp;&amp; ")) {
                    break;
                }
                else if (value[_].indexOf("&gt; ") >= 0) {
                    let listSplit = value[_].split("&gt; ");
                    listSplit[0] = listSplit[0].replaceAll("&gt;", ">");
                    if (!listSplit[0].trim().split('').every(char => char === ">")) {
                        notAdded = true;
                        break;
                    }
                    let listIndent = listSplit[0].trim().length * 4 + 4;
                    let listValue = value[_].substring(listIndent + 1, value[_].length);
                    if (listValue.length <= 0) {
                        notAdded = true;
                        break;
                    }
                    creatingList = true;
                    str += "<ul>";
                    for (let _index = 1; _index < listIndent / 4; _index++) {
                        str += "<ul>";
                    }
                    str += "<li>" + listValue + "</li>";
                    for (let _index = 0; _index < listIndent / 4; _index++) {
                        str += "</ul>";
                    }
                }
                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 = "";
        }
    }
    let code = CodeBlockDisableHTML(value, html);
    let formatted = FormatText(code);
    return formatted;
}

function CodeBlockDisableHTML(original, processed) {
    let returnArray = [];
    let originalIndex = 0;
    let processedIndex = 0;
    let whileEndIndex = original.length + processed.length;
    let processedCanAdd = true;
    let originalTurn = false;
    let processedContinueIndex = 0;
    while (whileEndIndex > 0) {
        if (originalTurn) {
            if (original[originalIndex].indexOf("```") != -1) {
                returnArray.push(original[originalIndex]);
                originalTurn = false;
                for (let _index = processedIndex; _index < processed.length; _index++) {
                    if (processed[_index].indexOf("```") != -1) {
                        processedContinueIndex = _index;
                        break;
                    }
                }
            }
            else {
                returnArray.push(original[originalIndex] + "<br>");
            }
            originalIndex++;
        }
        else {
            if (processedCanAdd) {
                if (processed[processedIndex].indexOf("```") != -1) {
                    if (processed[processedIndex].split("```").length == 2) {
                        returnArray.push(processed[processedIndex] + "<br>");
                        originalTurn = true;
                        processedCanAdd = false;
                        for (let _index = originalIndex; _index < original.length; _index++) {
                            if (original[_index].indexOf("```") != -1) {
                                originalIndex = _index + 1;
                                break;
                            }
                        }
                    }
                    else {
                        returnArray.push(processed[processedIndex]);
                        originalIndex = processedIndex + 1;
                    }
                }
                else {
                    returnArray.push(processed[processedIndex]);
                }
            }
            else {
                if (processedContinueIndex <= processedIndex) {
                    processedCanAdd = true;
                }
            }
            processedIndex++;
            if (processedIndex == processed.length) {
                break;
            }
        }
        whileEndIndex--;
    }
    return returnArray;
}

function GetCellData(text) {
    let returnData = {
        txt: text,
        width: "",
        colspan: 1,
        rowspan: 1
    }
    let startIndex = text.indexOf("{{");
    let endIndex = text.indexOf("}}");
    if (startIndex == 0 && endIndex != -1 && startIndex < endIndex) {
        let innerValues = text.substring(2).split("}}")[0].split(";");
        for (let _ in innerValues) {
            if (innerValues[_].indexOf("colspan=") != -1) {
                returnData.colspan = (Number(innerValues[_].replace("colspan=", "")) != NaN) ? Number(innerValues[_].replace("colspan=", "")) : 0;
                continue;
            }
            if (innerValues[_].indexOf("rowspan=") != -1) {
                returnData.rowspan = (Number(innerValues[_].replace("rowspan=", "")) != NaN) ? Number(innerValues[_].replace("rowspan=", "")) : 0;
                continue;
            }
            if (innerValues[_].indexOf("width=") != -1) {
                returnData.width = (innerValues[_].replace("width=", "").length > 0) ? "width: " + innerValues[_].replace("width=", "") : "";
                continue;
            }
        }
        returnData.txt = text.substring(endIndex + 2);
    }
    return returnData;
}

// 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, "==");
            // Media and style
            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 += `${giveText}${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;
}

// Generates link, image or audio HTML tag
function CreateMedia(givenText) {
    let indexes = [];
    indexes.push(GetIndexesOf(givenText, "[["));
    if (indexes[0].length <= 0) {
        return givenText;
    }
    indexes.push(GetIndexesOf(givenText, "\"]]").reverse());
    if (indexes[1].length <= 0) {
        return givenText;
    }
    let mediaCount = indexes[0].length;
    if (mediaCount > indexes[1].length) {
        mediaCount = indexes[1].length;
    }
    indexes = [];
    let offSet = 0;
    let arrayCount = 0;
    for (let _ = 0; _ < givenText.length; _++) {
        let _index = 0;
        offSet = 0;
        _index = givenText.indexOf("[[", _);
        if (_index > givenText.indexOf("\"]]", _) || _index == -1) {
            _index = givenText.indexOf("\"]]", _);
            if (_index == -1) {
                break;
            }
            arrayCount--;
            if (arrayCount < 0) {
                break;
            }
        }
        else {
            arrayCount++;
        }
        _ = _index;
        if (_index == givenText.indexOf("[[", _)) {
            if (mediaCount != indexes.length) {
                indexes.push([_index, -1]);
            }
        }
        else {
            while (indexes[arrayCount + offSet][1] != -1) {
                offSet++;
            }
            indexes[arrayCount + offSet][1] = _index + 1;
        }
    }
    let converted = "";
    let htmlArray = [];
    for (let _ = indexes.length - 1; _ >= 0; _--) {
        let mediaString = givenText.substring(indexes[_][0] + 2, indexes[_][1]);
        if (_ + 1 < indexes.length) {
            if (indexes[_][1] > indexes[_ + 1][1]) {
                mediaString = mediaString.substring(0, indexes[_ + 1][0] - indexes[_][0] - 2) + converted;
                mediaString = mediaString + givenText.substring(indexes[_ + 1][1] + 2, indexes[_][1]);
            }
            else {
                htmlArray.push([converted, _ + 1]);
            }
        }
        let mediaData;
        switch (mediaString.substring(0, 4)) {
            case "link":
                mediaData = ExtractMediaData(mediaString);
                if (mediaData.src.length <= 0) {
                    converted = "[[" + mediaString + "]]";
                    break;
                }
                if (mediaData.txt.length <= 0) {
                    mediaData.txt = mediaData.src;
                }
                converted = "<a href=\"" + mediaData.src + "\" " + (mediaData.defaultcss == false ? "class=\"no-link-css\"" : "")+ " style=\"" + mediaData.css + "\">" + mediaData.txt + "</a>";
                break;
            case "file":
                mediaData = ExtractMediaData(mediaString);
                if (mediaData.src.length <= 0) {
                    converted = "[[" + mediaString + "]]";
                    break;
                }
                let fileType = mediaData.src.split(".")[1];
                if (fileType == "mp3" || fileType == "ogg" || fileType == "wav") {
                    converted = "<div>" + mediaData.txt + "<br><audio style=\"" + mediaData.css + "\" controls><source src=\"/" + Topic() + "/load/" + mediaData.src + "\"></audio></div>";
                }
                else {
                    converted = "<div><img class=\"" + (mediaData.viewer == false ? "" : "image-click") + "\"" 
                    + " src=\"/" + Topic() + "/load/" + mediaData.src + "\" alt=\"\" style=\"" + mediaData.css + "\">"
                    + "<br>" + mediaData.txt + "</div>";
                }
                break;
            default:
                mediaData = ExtractMediaData(mediaString);
                if (mediaData.txt.length <= 0 || mediaData.css.length <= 0) {
                    converted = "[[" + mediaString + "]]";
                }
                else {
                    converted = "<span style=\"" + mediaData.css + "\">" + mediaData.txt + "</span>";
                }
                break;
        }
        if (_ == 0) {
            htmlArray.push([converted, _]);
        }
    }
    let html = "";
    for (let _ = 0; _ < htmlArray.length; _++) {
        if (_ == 0) {
            html = htmlArray[_][0] + givenText.substring(indexes[htmlArray[_][1]][1] + 2);
        }
        else {
            html = htmlArray[_][0] + givenText.substring(indexes[htmlArray[_][1]][1] + 2, indexes[htmlArray[_ - 1][1]][0]) + html;
        }
    }
    html = givenText.substring(0, indexes[htmlArray[htmlArray.length - 1][1]][0]) + html;
    return html;
}

function GetIndexesOf(text, characters) {
    let indexes = [];
    for (let _ = 0; _ < text.length; _++) {
        let _index = text.indexOf(characters, _);
        if (_index == -1) {
            break;
        }
        else {
            _ = _index;
            indexes.push(_index);
        }
    }
    return indexes;
}

function ExtractMediaData(mediaString) {
    let mediaArray = mediaString.split("|");
    let mediaData = {
        src: "",
        txt: "",
        viewer: true,
        css: "",
        defaultcss: true
    };
    for (let _ = 0; _ < mediaArray.length; _++) {
        switch (mediaArray[_].substring(0, 5)) {
            case "link=":
                mediaData.src = mediaArray[_].substring(6, mediaArray[_].length - 1);
                break;
            case "file=":
                let source = mediaArray[_].substring(6, mediaArray[_].length - 1);
                source = source.split(" noviewer");
                if (source.length == 2) {
                    mediaData.viewer = false;
                }
                mediaData.src = source[0];
                break;
            case "text=":
                mediaData.txt = mediaArray[_].substring(6, mediaArray[_].length - 1);
                break;
            case "style":
                mediaData.css = mediaArray[_].substring(7, mediaArray[_].length - 1);
                if (mediaData.css.length == 0) {
                    mediaData.defaultcss = false;
                }
                break;
        }
    }
    return mediaData;
}

// 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;
}