class PopupService {


    async SendMessage(eventName, callback) {
        chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, { event: eventName }, callback);
        });
    }

    async GetHyperlinks() {
        const a = this;
        const baseUrl = await a.GetLocation();

        return new Promise(function(resolve) {
            a.SendMessage("GetNodes", async function(payload) {
                // let result = {
                //     items: payload.copy(),
                //     totalCount: payload.length,
                //     distinctCount: 0
                // };

                // result.items = result.items.orderBy("innerText");
                // result.items = result.items.distinct();

                // result.distinctCount = result.items.length;

                // Populate occurrence counter
                // for (let i=0; i<result.items.length; i++) {
                //     result.items[i].occurrence = payload.filter(item => JSON.stringify(item) === JSON.stringify(result.items[i])).length;
                // }

                // resolve(result);

                // console.log(payload);

                resolve(payload.copy());
            });
        });

    }

    async GetLocation() {
        const a = this;

        return new Promise(function(resolve) {
            a.SendMessage("GetLocation", function(payload) {
                resolve(payload);
            });
        });
    }

}


class ContentService {

    GenerateCheckBox(num, label, checked) {
        let html = "";
        html += "<div class=\"form-check form-switch\">";
        html += "<input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"checkbox" + num + "\" " + (checked ? "checked" : "") + ">";
        html += "<label class=\"form-check-label\" for=\"checkbox" + num + "\">" + label + "</label>";
        html += "</div>";

        return html;
    }

    GenerateCols(...args) {
        let html = "";

        for (let i=0; i<args.length; i++) {
            html += "<div class=\"col\">" + args[i] + "</div>";
        }

        return html;
    }

    GenerateRow(...args) {
        const a = this;

        if (args.length === 1) {
            if (Object.getDataType(args[0]) == "array") {
                args = args[0];
            }
        }

        let result = "";
        for (let i=0; i<args.length; i++) {
            result = result + a.GenerateRowCell(args[i]);
        }

        return "<tr>" + result + "</tr>";
    }

    GenerateRowCell(value) {
        return "<td class=\"\"><input type=\"text\" class=\"display\" readonly=\"readonly\" value=\"" + value + "\" /></td>";
    }

}


class AContentService extends ContentService {
    ContainerPanel = null;
    Panel1 = null;
    Button1 = null;
    Button2 = null;
    Label1 = null;
    Table1 = null;

    #PopupService = null;
    #TableLabel = "Results";


    constructor(popupService) {
        super();

        this.#PopupService = popupService;
    }

    InitialiseComponents(){
        const a = this;

        a.ContainerPanel = document.getElementById("nav-hyperlinks");
        a.Panel1 = a.ContainerPanel.querySelectorAll("div[role='options']")[0];
        a.Button1 = a.ContainerPanel.querySelectorAll("button")[0];
        a.Button2 = a.ContainerPanel.querySelectorAll("button")[1];
        a.Label1 = a.ContainerPanel.querySelectorAll("span[role='table-heading']")[0];
        a.Table1 = a.ContainerPanel.querySelectorAll("table")[0];

        a.Clear();

        let col1 = "";
        col1 += a.GenerateCheckBox(1, "Show Anchor as HTML", false);
        col1 += a.GenerateCheckBox(3, "Sort By Anchor Text", true);
        col1 += a.GenerateCheckBox(2, "Trim Anchor Text", true);
        col1 += a.GenerateCheckBox(4, "Resolve Relative URL", false);
        col1 += a.GenerateCheckBox(12, "Hide External Links", true);

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

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

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

        a.#writeOptionsPanel(html);

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

            await a.Search();

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


    Clear() {
        const a = this;

        a.#writeOptionsPanel("");

        a.#clearTable();
    }

    async Search() {
        const a = this;
        const thead = a.Table1.querySelectorAll("thead")[0];
        const tbody = a.Table1.querySelectorAll("tbody")[0];

        a.#clearTable();

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

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

        a.Label1.innerText = a.#TableLabel + " (" + totalCount + ")";

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

        if (newResults.length != totalCount) {
            a.Label1.innerText = a.#TableLabel + " (" + newResults.length + "/" + totalCount + ")";
        }

        for (let i=0; i<newResults.length; i++) {
            const item = newResults[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);
        }

    }

    #clearTable() {
        const a = this;

        a.Label1.innerText = a.#TableLabel;

        const thead = a.Table1.querySelectorAll("thead")[0];
        const tbody = a.Table1.querySelectorAll("tbody")[0];
        thead.innerHTML = "";
        tbody.innerHTML = "";
    }

    async #filterSearch(items) {
        const a = this;
        const currentUrl = await 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;
                }
            }

            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();
            }

            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:  "Occurrence" }
        ];

        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.Panel1 == null) {
            return false;
        }

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

        return result[0].checked;
    }

    #writeOptionsPanel(htmlContent) {
        const a = this;

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

        a.Panel1.innerHTML = htmlContent;
    }

}


const popupService = new PopupService();
const aContentService = new AContentService(popupService);


document.addEventListener("DOMContentLoaded", async function(event) {

    aContentService.InitialiseComponents();

    // aContentService.Button1.addEventListener('click', async function (e) {
    //     const body = aContentService.Table1.querySelectorAll("tbody")[0];
    //     body.innerHTML = "";

    //     const result = await popupService.GetHyperlinks();

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

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

    //         // memoBox1.innerText = absoluteUrl.hash;
    //         // console.log(absoluteUrl);

    //         body.innerHTML += aContentService.GenerateRow(item.innerHTML, item.href, item.title, item.target);
    //     }
    // });

    // PageAssetsCRX.HomeApp.mount("#App1");

    // const panel2 = document.getElementById("nav-hyperlinks");

    // const optionsPanel = panel2.querySelectorAll("div[role='options']")[0];

    // optionsPanel.innerHTML = "";

    // let html = "";
    // html += contentService.GenerateCheckBox(1, "Show Anchor as HTML", false);
    // html += contentService.GenerateCheckBox(2, "Trim Anchor Text", true);
    // html += contentService.GenerateCheckBox(3, "Sort By Anchor Text", true);
    // html += contentService.GenerateCheckBox(4, "Resolve Relative URL", true);
    // html += contentService.GenerateCheckBox(5, "Hide Duplicates", true);

    // html += contentService.GenerateCheckBox(6, "Show Title", true);
    // html += contentService.GenerateCheckBox(7, "Show Target", true);
    // html += contentService.GenerateCheckBox(8, "Show Rel", true);
    // html += contentService.GenerateCheckBox(9, "Show Type", true);
    // html += contentService.GenerateCheckBox(10, "Show Occurrence", true);

    // optionsPanel.innerHTML = html;



    // const label1 = document.getElementById("label1");
    // const button1 = document.getElementById("button1");
    // const checkbox1 = document.getElementById("checkbox1");
    // const table1 = document.getElementById("table1");
    // const memoBox1 = document.getElementById("memoBox1");

    // const messageService = new MessageService();

    // memoBox1.focus();


    // button1.addEventListener('click', async function (e) {
    //     const body = table1.getElementsByTagName("tbody")[0];
    //     body.innerHTML = "";

    //     const result = await popupService.GetHyperlinks();

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

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

    //         // memoBox1.innerText = absoluteUrl.hash;
    //         // console.log(absoluteUrl);

    //         body.innerHTML += popupService.GenerateRow(item.innerHTML, item.href, item.title, item.target);
    //     }
    // });



    // memoBox1.innerText = await popupService.GetLocation();

    // const body = table1.getElementsByTagName("tbody")[0];
    // body.innerHTML = "";

    // const result = await popupService.GetHyperlinks();

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

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

    //     // memoBox1.innerText = absoluteUrl.hash;
    //     // console.log(absoluteUrl);

    //     body.innerHTML += popupService.GenerateRow(item.text, item.href, item.title, item.target);
    // }

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

    //     body.innerHTML += popupService.GenerateRow(item.text, item.href, item.title, item.occurrence);
    // }



/*
    popupService.SendMessage("GetNodes", async function(payload) {
        const body = table1.getElementsByTagName("tbody")[0];
        body.innerHTML = "";

        let result = payload;
        const totalCount = result.length;

        result = result.distinct();
        result = result.orderBy("text");

        const distinctCount = result.length;

        if (totalCount <= 0) {
            label1.innerHTML = "Hyperlinks (0)";
        } else if (totalCount == distinctCount) {
            label1.innerHTML = "Hyperlinks (" + totalCount + ")";
        } else {
            label1.innerHTML = "Hyperlinks (" + distinctCount + "/" + totalCount + ")";
        }

        // memoBox1.innerText = JSON.stringify(e);

        for( let i=0; i<result.length; i++) {
            body.innerHTML += popupService.GenerateRow(result[i].text, result[i].href, result[i].title);
        }

    });
*/




/*
    chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, { event: "GetNodes" }, async function(payload) {

            const body = table1.getElementsByTagName("tbody")[0];
            body.innerHTML = "";

            let result = payload;
            const totalCount = result.length;

            result = result.distinct();
            result = result.orderBy("text");

            const distinctCount = result.length;

            if (totalCount <= 0) {
                label1.innerHTML = "Hyperlinks (0)";
            } else if (totalCount == distinctCount) {
                label1.innerHTML = "Hyperlinks (" + totalCount + ")";
            } else {
                label1.innerHTML = "Hyperlinks (" + distinctCount + "/" + totalCount + ")";
            }


            // memoBox1.innerText = JSON.stringify(e);


            for( let i=0; i<result.length; i++) {
                body.innerHTML += popupService.GenerateRow(result[i].text, result[i].href, result[i].title);
            }


        });



        // chrome.tabs.sendMessage(tabs[0].id, { data: "hello" }, response => {

        // Print response on popup.html

        // var msg = document.createElement("h3");

        // msg.innerHTML = "H1:" + response;

        // document.getElementById("container”).appendChild(msg);

        // memoBox1.innerHTML = response;

            // alert("!");
        // });
    });
*/



    // document.getElementsByTagName("a").array.forEach(e => {
    //     memoBox1.innerHTML += e.href + "\n";
    // });

//     var switch1 = document.getElementById("switch1");
//     var switch2 = document.getElementById("switch2");
//     var switch3 = document.getElementById("switch3");
//     var switch4 = document.getElementById("switch4");
//     var switch5 = document.getElementById("switch5");
//     var switch6 = document.getElementById("switch6");

//     // read local storage
//     chrome.storage.local.get(['switch1'], function(result) {
//         switch1.checked = result.switch1;
//     });
//     chrome.storage.local.get(['switch2'], function(result) {
//         switch2.checked = result.switch2;
//     });
//     chrome.storage.local.get(['switch3'], function(result) {
//         switch3.checked = result.switch3;
//     });
//     chrome.storage.local.get(['switch4'], function(result) {
//         switch4.checked = result.switch4;
//     });
//     chrome.storage.local.get(['switch5'], function(result) {
//         switch5.checked = result.switch5;
//     });
//     chrome.storage.local.get(['switch6'], function(result) {
//         switch6.checked = result.switch6;
//     });

//     // set values
//     switch1.addEventListener('change', function (e) {
//         chrome.storage.local.set({ switch1: e.target.checked}, function() {
//             // do nothing
//         });
//     });
//     switch2.addEventListener('change', function (e) {
//         chrome.storage.local.set({ switch2: e.target.checked}, function() {
//             // do nothing
//         });
//     });
//     switch3.addEventListener('change', function (e) {
//         chrome.storage.local.set({ switch3: e.target.checked}, function() {
//             // do nothing
//         });
//     });
//     switch4.addEventListener('change', function (e) {
//         chrome.storage.local.set({ switch4: e.target.checked}, function() {
//             // do nothing
//         });
//     });
//     switch5.addEventListener('change', function (e) {
//         chrome.storage.local.set({ switch5: e.target.checked}, function() {
//             // do nothing
//         });
//     });
//     switch6.addEventListener('change', function (e) {
//         chrome.storage.local.set({ switch6: e.target.checked}, function() {
//             // do nothing
//         });
//     });

});