import {Configurator, DocumentDirectory} from "./fileutils";
import * as path from "path";
import {buildCardsFromConfig, buildUiFromConfig} from "./viewFactory";

function register() {
    let searchBar = $("#searchfield");
    let searchButton = $("#searchbutton");
    searchBar.on("keyup", (evt) => {
        if ("Enter" === evt.code) {
            let term = searchBar.val().toString();
            if (!term || 0 === term.length) {
                reset()
            } else {
                search(term);
            }

        } else {
            let term = searchBar.val().toString();
            if (!term || 0 === term.length) {
                reset()
            }
        }
    });


    searchButton.on("click", () => {
        let term = searchBar.val().toString();
        if (!term || 0 === term.length) {
            reset()
        } else {
            search(term);
        }
    })
}

function reset() {
    buildUiFromConfig("resources-landing-page.json");
}

function search(term: string) {
    let webCards = getWebCardsWithSearchTerm(term);
    let fileCards = getFileCardsWithSearchTerm(term);

    copyMissingKeys(webCards, fileCards);

    buildCardsFromConfig(webCards, fileCards);
    expandAllContainers();
}

function copyMissingKeys(webCards: object, fileCards: Map<string, object>) {
    let elementConfig = Configurator.loadAppConfig("resources-landing-page.json");
    let containerKeys = Object.keys(elementConfig);
    for (let containerKey of containerKeys) {
        let container = webCards[containerKey];
        let elementContainer = elementConfig[containerKey];
        for (let [key, value] of fileCards) {
            if (!container[key]) {
                let original = elementContainer[key];
                original["cards"] = [];
                container[key] = original;
            }
        }
    }
}

function getFileCardsWithSearchTerm(term): Map<string, object> {
    let map = new Map<string, object>()
    let directoryPath = path.join(__dirname, "../assets/resources");
    let fileCards = new DocumentDirectory(directoryPath).getCards();
    for (let [key, value] of fileCards) {
        for (let card of value) {
            if (cardContainsTerm(term, card)) {
                addToFileMap(map, key, highlightCardTerm(term, card));
            }
        }
    }
    return map;
}

function getWebCardsWithSearchTerm(term): object {
    let map = {};
    let elementConfig = Configurator.loadAppConfig("resources-landing-page.json");
    let containerKeys = Object.keys(elementConfig);
    for (let i = 0, l = containerKeys.length; i < l; i++) {
        let containerKey = containerKeys[i];
        map[containerKey] = {};
        let container = elementConfig[containerKey];
        let categoryKeys = Object.keys(container);
        for (let categoryIdx in categoryKeys) {
            let categoryKey = categoryKeys[categoryIdx]
            let category = container[categoryKey];
            let cards = category.cards;
            for (let j = 0, k = cards.length; j < k; j++) {
                let card = cards[j];
                if (cardContainsTerm(term, card)) {
                    addToWebMap(map, containerKey, categoryKey, category["description"], highlightCardTerm(term, card));
                }
            }
        }
    }
    return map;
}

function addToWebMap(map: object, containerKey: string, categoryKey: string, categoryDescription: string, card: object) {
    let container = map[containerKey];
    if (!container) {
        container = {};
    }
    let category = container[categoryKey];
    if (!category) {
        category = {"description": categoryDescription, "cards": []}
    }
    category["cards"].push(card);
    container[categoryKey] = category;
    map[containerKey] = container;
}

function addToFileMap(map: Map<string, object>, categoryKey: string, card) {
    if (!map.get(categoryKey)) {
        map.set(categoryKey, []);
    }
    let cards = map.get(categoryKey) as Array<object>;
    cards.push(card);
    map.set(categoryKey, cards);
}

function cardContainsTerm(term: string, card: object): boolean {
    let titleContains = card["title"].toLowerCase().includes(term.toLowerCase());
    let descriptionContains = card["description"].toLowerCase().includes(term.toLowerCase());

    let keywordContains = false;
    if (card["keywords"]) {
        keywordContains = card["keywords"].toLowerCase().includes(term.toLowerCase());
    }

    //todo: add keywords
    return titleContains || descriptionContains || keywordContains;
}

function highlightCardTerm(term: string, card: object): object {
    let regexTerm = escapeRegExp(term);
    let pattern = new RegExp(regexTerm, 'ig');
    card["title"] = card["title"].replace(pattern, `<span class="highlight">$&</span>`);
    card["description"] = card["description"].replace(pattern, `<span class="highlight">$&</span>`);
    return card;
}

function escapeRegExp(term: string): string {
    return term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

function expandAllContainers() {
    let containers = $('[id$="collapser"]')
    for (let container of containers) {
        container.click()
    }

}

register()