import '../../../literyz-js/extensions.dist.js';

import ContentService from './content-service.js';


class AContentService extends ContentService {
    #containerPanel = null;
    #popupService = null;


    constructor(popupService) {
        super();

        this.#popupService = popupService;
    }

    InitialiseComponents() {
        const a = this;

        a.Clear();

        a.#initialiseComponents_Options();
        a.#initialiseComponents_Filters();

        a.Button1.addEventListener('click', async function (e) {
            a.Button2.disabled = true;

            a.TextBox1.value = "";

            await a.Search();

            a.Button2.disabled = false;
        });

        a.Button2.addEventListener('click', async function (e) {
            a.Button2.disabled = true;

            await a.Search();

            a.Button2.disabled = false;
        });
    }

    #initialiseComponents_Options() {
        const a = this;

        let col1 = "";
        col1 += a.GenerateCheckBox(1, "Show Anchor as HTML", false);
        col1 += a.GenerateCheckBox(4, "Resolve Relative URL", false);

        let col2 = "";
        col2 += a.GenerateCheckBox(3, "Sort By Anchor Text", true);
        col2 += a.GenerateCheckBox(2, "Trim Anchor Text", true);

        let html = a.GenerateCols(col1, col2);

        a.SetHtml(a.Panel1, html);
    }

    #initialiseComponents_Filters() {
        const a = this;

        let col1 = "";
        col1 += a.GenerateCheckBox(12, "Hide External Links", true);
        col1 += a.GenerateCheckBox(5, "Hide Duplicates", true);
        col1 += a.GenerateCheckBox(14, "Hide Blank Anchors", true);
        col1 += a.GenerateCheckBox(15, "Hide Blank Links", true);
        col1 += a.GenerateCheckBox(11, "Hide Fragments", true);
        col1 += a.GenerateCheckBox(13, "Hide Mailto/Tel", true);
        col1 += a.GenerateCheckBox(16, "Hide Javascript", true);

        let col2 = "";
        col2 += a.GenerateCheckBox(6, "Show Title", true);
        col2 += a.GenerateCheckBox(7, "Show Target", false);
        col2 += a.GenerateCheckBox(8, "Show Rel", false);
        col2 += a.GenerateCheckBox(9, "Show Type", false);
        col2 += a.GenerateCheckBox(10, "Show Count", false);

        let html = a.GenerateCols(col1, col2);

        a.SetHtml(a.Panel2, html);
    }


    get Button1() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("button")[0];
    }

    get Button2() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("button")[1];
    }

    get Container() {
        const a = this;

        if (a.#containerPanel == null) {
            a.#containerPanel = document.getElementById("nav-hyperlinks");
        }

        return a.#containerPanel;
    }

    get Label1() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("[role='label']")[0];
    }

    get MemoBox1() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("textarea")[0];
    }

    get Panel1() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("div[role='options']")[0];
    }

    get Panel2() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("div[role='filters']")[0];
    }

    get Table1() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("table")[0];
    }

    get TextBox1() {
        const a = this;

        if (a.Container == null) {
            return null;
        }

        return a.Container.querySelectorAll("input[role='textbox']")[0];
    }


    Clear() {
        const a = this;

        a.Table1.style.display = 'none';
        a.MemoBox1.style.display = 'none';

        a.SetHtml(a.Panel1, "");
        a.SetHtml(a.Panel2, "");
    }

    async Search() {
        const a = this;

        a.Label1.innerText = "";

        a.Table1.style.display = 'none';
        a.MemoBox1.style.display = 'none';

        const result = await a.#popupService.GetHyperlinks();
        const totalCount = result.length;

        const newResults = await a.#filterResult(result.copy());

        if (newResults.length == totalCount) {
            a.Label1.innerText = "Showing " + totalCount + " result" + (totalCount == 1 ? "" : "s");
        } else {
            a.Label1.innerText = "Showing " + newResults.length + " of " + totalCount + " result" + (totalCount == 1 ? "" : "s");
        }

        switch (a.#getComboBox(2)) {
            case "table":
                a.#renderTable(newResults);
                break;
            case "csv":
                a.#renderCSV(newResults);
                break;
            case "links":
                a.#renderLinks(newResults);
                break;
            default:
                break;
        }
    }

    async #filterResult(items) {
        const a = this;
        const currentUrl = await a.#popupService.GetLocation();
        const currentHostname = (new URL(currentUrl)).hostname;

        let result = [];

        for (let i=0; i<items.length; i++) {
            const item = items[i];

            // Hide fragments
            if (a.#getCheckBox(11)) {
                if (item.href.startsWith("#")) {
                    continue;
                }
            }

            // Hide blank links
            if (a.#getCheckBox(15)) {
                if (String.isNullOrWhitespace(item.href)) {
                    continue;
                }
            }

            // Hide mailto/tel
            if (a.#getCheckBox(13)) {
                if (item.href.toLowerCase().startsWith("telno:") || item.href.toLowerCase().startsWith("mailto:")) {
                    continue;
                }
            }

            // Hide javascript
            if (a.#getCheckBox(16)) {
                if (item.href.toLowerCase().startsWith("javascript:")) {
                    continue;
                }
            }

            const absoluteUrl = new URL(item.href, currentUrl);

            // Hide external links
            if (a.#getCheckBox(12)) {
                if (currentHostname != absoluteUrl.hostname) {
                    continue;
                }
            }

            // Show anchor as html
            let text = (a.#getCheckBox(1) ? item.innerHTML : item.innerText);

            // Hide blank anchors
            if (a.#getCheckBox(14)) {
                if (String.isNullOrWhitespace(text)) {
                    continue;
                }
            }

            // Resolve relative url
            const href = (a.#getCheckBox(4) ? absoluteUrl.href : item.href);

            // Trim anchor text
            if (a.#getCheckBox(2)) {
                text = text.trim();
            }

            // Search term
            if (!String.isNullOrWhitespace(a.TextBox1.value)) {
                if (a.#getComboBox(1) == "anchor") {
                    if (!text.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
                        continue;
                    }
                } else {
                    if (!href.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
                        continue;
                    }
                }
            }

            result.push({
                text: text,
                href: href,
                title: (a.#getCheckBox(6) ? item.title : ""),
                target: (a.#getCheckBox(7) ? item.target : ""),
                rel: (a.#getCheckBox(8) ? item.rel : ""),
                type: (a.#getCheckBox(9) ? item.type : ""),
                occurrence: ""
              });
        }

        // Show occurrence
        if (a.#getCheckBox(10)) {
            // Calc occurrences, store in cache
            let occurrenceCache = [];
            for (let i=0; i<result.length; i++) {
                const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;

                occurrenceCache.push(occurrence);
            }

            // Update result with occurrence
            for (let i=0; i<result.length; i++) {
                result[i].occurrence = occurrenceCache[i];
            }
        }

        // Hide duplicates
        if (a.#getCheckBox(5)) {
            result = result.distinct();
        }

        // Sort by anchor text
        if (a.#getCheckBox(3)) {
            result = result.orderBy("text");
        }

        return result;
    }

    #generateTHeader() {
        const a = this;
        const columns = [
            { id: 6, name: "Title" },
            { id: 7, name:  "Target" },
            { id: 8, name:  "Rel" },
            { id: 9, name:  "Type" },
            { id: 10, name:  "Count" }
        ];

        let html = "";
        html += "<th>Anchor Text</th>";
        html += "<th>Address</th>";

        for (let i=0; i<columns.length; i++) {
            if (a.#getCheckBox(columns[i].id)) {
                html += "<th>" + columns[i].name + "</th>";
            }
        }

        return html;
    }

    #getCheckBox(num) {
        const a = this;

        if (a.Container == null) {
            return false;
        }

        const result = a.Container.querySelectorAll("input[name='checkbox" + num + "']");
        if (result.length <= 0) {
            return false;
        }

        return result[0].checked;
    }

    #getComboBox(num) {
        const a = this;

        if (a.Container == null) {
            return "";
        }

        const result = a.Container.querySelectorAll("select[name='comboBox" + num + "']");
        if (result.length <= 0) {
            return "";
        }

        return result[0].value;
    }

    #getRadioGroup(num) {
        const a = this;

        if (a.Container == null) {
            return "";
        }

        const result = a.Container.querySelectorAll("input[name='radioGroup" + num + "']:checked");
        if (result.length <= 0) {
            return "";
        }

        return result[0].value;
    }

    #renderTable(results) {
        const a = this;
        const thead = a.Table1.querySelectorAll("thead")[0];
        const tbody = a.Table1.querySelectorAll("tbody")[0];

        thead.innerHTML = "";
        tbody.innerHTML = "";

        a.Table1.style.display = 'table';

        // Write thead
        thead.innerHTML = "<tr>" + a.#generateTHeader() + "</tr>";

        // Write tbody
        for (let i=0; i<results.length; i++) {
            const item = results[i];

            let row = [ item.text, item.href ];

            if (a.#getCheckBox(6)) {
                row.push(item.title);
            }

            if (a.#getCheckBox(7)) {
                row.push(item.target);
            }

            if (a.#getCheckBox(8)) {
                row.push(item.rel);
            }

            if (a.#getCheckBox(9)) {
                row.push(item.type);
            }

            if (a.#getCheckBox(10)) {
                row.push(item.occurrence);
            }

            tbody.innerHTML += a.GenerateRow(row);
        }
    }

    #renderCSV(results) {
        const a = this;

        a.MemoBox1.value = "";
        a.MemoBox1.style.display = 'inline-block';

        for (let i=0; i<results.length; i++) {
            const item = results[i];

            let row = [ item.text, item.href ];

            if (a.#getCheckBox(6)) {
                row.push(item.title);
            }

            if (a.#getCheckBox(7)) {
                row.push(item.target);
            }

            if (a.#getCheckBox(8)) {
                row.push(item.rel);
            }

            if (a.#getCheckBox(9)) {
                row.push(item.type);
            }

            if (a.#getCheckBox(10)) {
                row.push(item.occurrence);
            }

            a.MemoBox1.value += a.GenerateCSVLine("\t", row);
            a.MemoBox1.value += "\n";
        }
    }

    #renderLinks(results) {
        const a = this;

        a.MemoBox1.value = "";
        a.MemoBox1.style.display = 'inline-block';

        for (let i=0; i<results.length; i++) {
            const item = results[i];

            a.MemoBox1.value += a.GenerateCSVLine("\t", [ item.href ]);
            a.MemoBox1.value += "\n";
        }
    }

}


export default AContentService;