"use strict";

const router = require("../router.js");
const keyboard = require("../util/keyboard.js");
const views = require("../util/views.js");

const holderTemplate = views.getTemplate("manual-pager");
const navTemplate = views.getTemplate("manual-pager-nav");

function _removeConsecutiveDuplicates(a) {
    return a.filter((item, pos, ary) => {
        return !pos || item !== ary[pos - 1];
    });
}

function _getVisiblePageNumbers(currentPage, totalPages) {
    const threshold = 2;
    let pagesVisible = [];
    for (let i = 1; i <= threshold; i++) {
        pagesVisible.push(i);
    }
    for (let i = totalPages - threshold; i <= totalPages; i++) {
        pagesVisible.push(i);
    }
    for (let i = currentPage - threshold; i <= currentPage + threshold; i++) {
        pagesVisible.push(i);
    }
    pagesVisible = pagesVisible.filter((item, pos, ary) => {
        return item >= 1 && item <= totalPages;
    });
    pagesVisible = pagesVisible.sort((a, b) => {
        return a - b;
    });
    pagesVisible = _removeConsecutiveDuplicates(pagesVisible);
    return pagesVisible;
}

function _getPages(
    currentPage,
    pageNumbers,
    limit,
    defaultLimit,
    removedItems
) {
    const pages = new Map();
    let prevPage = 0;
    for (let page of pageNumbers) {
        if (page !== prevPage + 1) {
            pages.set(page - 1, { ellipsis: true });
        }
        pages.set(page, {
            number: page,
            offset:
                (page - 1) * limit - (page > currentPage ? removedItems : 0),
            limit: limit === defaultLimit ? null : limit,
            active: currentPage === page,
        });
        prevPage = page;
    }
    return pages;
}

class ManualPageView {
    constructor(ctx) {
        this._hostNode = document.getElementById("content-holder");
        views.replaceContent(this._hostNode, holderTemplate());
    }

    run(ctx) {
        const offset = parseInt(ctx.parameters.offset || 0);
        const limit = parseInt(ctx.parameters.limit || ctx.defaultLimit);
        this.clearMessages();
        views.emptyContent(this._pageNavNode);

        ctx.requestPage(offset, limit).then(
            (response) => {
                ctx.pageRenderer({
                    parameters: ctx.parameters,
                    response: response,
                    hostNode: this._pageContentHolderNode,
                });

                keyboard.bind(["a", "left"], () => {
                    this._navigateToPrevNextPage("prev");
                });
                keyboard.bind(["d", "right"], () => {
                    this._navigateToPrevNextPage("next");
                });

                let removedItems = 0;
                if (response.total) {
                    this._refreshNav(
                        offset,
                        limit,
                        response.total,
                        removedItems,
                        ctx
                    );
                }

                if (!response.results.length) {
                    this.showInfo("No data to show");
                }

                response.results.addEventListener("remove", (e) => {
                    removedItems++;
                    this._refreshNav(
                        offset,
                        limit,
                        response.total,
                        removedItems,
                        ctx
                    );
                });

                views.syncScrollPosition();
            },
            (response) => {
                this.showError(response.message);
            }
        );
    }

    get pageHeaderHolderNode() {
        return this._hostNode.querySelector(".page-header-holder");
    }

    get _pageContentHolderNode() {
        return this._hostNode.querySelector(".page-content-holder");
    }

    get _pageNavNode() {
        return this._hostNode.querySelector(".page-nav");
    }

    clearMessages() {
        views.clearMessages(this._hostNode);
    }

    showSuccess(message) {
        views.showSuccess(this._hostNode, message);
    }

    showError(message) {
        views.showError(this._hostNode, message);
    }

    showInfo(message) {
        views.showInfo(this._hostNode, message);
    }

    _navigateToPrevNextPage(className) {
        const linkNode = this._hostNode.querySelector("a." + className);
        if (linkNode.classList.contains("disabled")) {
            return;
        }
        router.show(linkNode.getAttribute("href"));
    }

    _refreshNav(offset, limit, total, removedItems, ctx) {
        const currentPage = Math.floor((offset + limit - 1) / limit) + 1;
        const totalPages = Math.ceil((total - removedItems) / limit);
        const pageNumbers = _getVisiblePageNumbers(currentPage, totalPages);
        const pages = _getPages(
            currentPage,
            pageNumbers,
            limit,
            ctx.defaultLimit,
            removedItems
        );

        views.replaceContent(
            this._pageNavNode,
            navTemplate({
                getClientUrlForPage: ctx.getClientUrlForPage,
                prevPage: Math.min(totalPages, Math.max(1, currentPage - 1)),
                nextPage: Math.min(totalPages, Math.max(1, currentPage + 1)),
                currentPage: currentPage,
                totalPages: totalPages,
                pages: pages,
            })
        );
    }
}

module.exports = ManualPageView;