<template>
    <nav class="sf-pagination">
        <!-- @slot Custom markup for previous page button -->
        <slot
            name="prev"
            v-bind="{ isDisabled: !canGoPrev, go, prev: getPrev }"
        >
            <div v-if="hasArrows" class="sf-pagination__item prev">
                <component
                    :is="componentIs"
                    :class="{
                        'sf-button--pure': !hasRouter,
                        'sf-arrow--transparent': !hasRouter && !canGoPrev,
                    }"
                    :link="hasRouter ? getLinkTo(getPrev) : null"
                    :disabled="!hasRouter && !canGoPrev ? true : false"
                    aria-label="Go to previous page"
                    data-testid="pagination-button-prev"
                    @click="hasRouter ? null : go(getPrev)"
                >
                    <SfIcon icon="arrow_left" size="1.125rem" />
                </component>
            </div>
        </slot>
        <template v-if="showFirst">
            <slot name="number" v-bind="{ page: 1 }">
                <component
                    :is="componentIs"
                    class="sf-pagination__item"
                    :class="{
                        'sf-button--pure': !hasRouter,
                    }"
                    :link="hasRouter ? getLinkTo(1) : null"
                    @click="hasRouter ? null : go(1)"
                >
                    1
                </component>
            </slot>
            <slot v-if="firstVisiblePageNumber > 2" name="points">
                <div class="sf-pagination__item">
                    ...
                </div>
            </slot>
        </template>
        <template v-for="page in limitedPageNumbers">
            <slot name="number" v-bind="{ page, currentPage }">
                <component
                    :is="currentPage === page ? 'span' : componentIs"
                    :key="page"
                    class="sf-pagination__item"
                    :class="{
                        'sf-button--pure': !hasRouter && currentPage !== page,
                        current: currentPage === page,
                    }"
                    :link="
                        hasRouter && currentPage !== page
                            ? getLinkTo(page)
                            : null
                    "
                    @click="
                        !hasRouter && currentPage !== page ? go(page) : null
                    "
                >
                    {{ page }}
                </component>
            </slot>
        </template>
        <template v-if="showLast">
            <slot v-if="lastVisiblePageNumber < total - 1" name="points">
                <div class="sf-pagination__item">
                    ...
                </div>
            </slot>
            <slot name="number" v-bind="{ page: total }">
                <component
                    :is="componentIs"
                    class="sf-pagination__item"
                    :class="{
                        'sf-button--pure': !hasRouter,
                    }"
                    :link="hasRouter ? getLinkTo(total) : null"
                    @click="hasRouter ? null : go(total)"
                >
                    {{ total }}
                </component>
            </slot>
        </template>
        <!-- @slot Custom markup for previous page button -->
        <slot
            name="next"
            v-bind="{ isDisabled: !canGoNext, go, next: getNext }"
        >
            <div v-if="hasArrows" class="sf-pagination__item next">
                <component
                    :is="componentIs"
                    :class="{
                        'sf-button--pure': !hasRouter,
                        'sf-arrow--transparent': !hasRouter && !canGoNext,
                    }"
                    :link="hasRouter ? getLinkTo(getNext) : null"
                    :disabled="!hasRouter && !canGoNext ? true : false"
                    aria-label="Go to previous next"
                    data-testid="pagination-button-next"
                    @click="hasRouter ? null : go(getNext)"
                >
                    <SfIcon icon="arrow_right" size="1.125rem" />
                </component>
            </div>
        </slot>
    </nav>
</template>
<script>
    import SfIcon from '../../atoms/SfIcon/SfIcon.vue';
    import SfLink from '../../atoms/SfLink/SfLink.vue';
    import SfButton from '../../atoms/SfButton/SfButton.vue';

    export default {
        name: 'SfPagination',
        components: {
            SfIcon,
            SfLink,
            SfButton,
        },
        props: {
            /**
             * Total number of pages
             */
            total: {
                type: Number,
                default: 0,
            },
            /**
             * Maximum visible pagination items
             */
            visible: {
                type: Number,
                default: 5,
            },
            /**
             * Status of arrows display
             */
            hasArrows: {
                type: Boolean,
                default: true,
            },
            /**
             * Current page number, for non router
             */
            current: {
                type: Number,
                default: 1,
            },
            /**
             * Name of page query param for router
             */
            pageParamName: {
                type: String,
                default: 'page',
            },
        },
        computed: {
            hasRouter() {
                return this.$route;
            },
            componentIs() {
                return this.hasRouter ? 'SfLink' : 'SfButton';
            },
            currentPage() {
                return this.hasRouter
                    ? this.$route.query[this.pageParamName]
                        ? parseInt(this.$route.query[this.pageParamName], 10)
                        : 1
                    : this.current;
            },
            getPrev() {
                return this.currentPage === this.firstVisiblePageNumber
                    ? this.currentPage
                    : this.currentPage - 1;
            },
            canGoPrev() {
                return this.currentPage !== this.firstVisiblePageNumber;
            },
            getNext() {
                return this.currentPage === this.lastVisiblePageNumber
                    ? this.currentPage
                    : this.currentPage + 1;
            },
            canGoNext() {
                return this.currentPage !== this.lastVisiblePageNumber;
            },
            showFirst() {
                return this.firstVisiblePageNumber > 1;
            },
            showLast() {
                return this.lastVisiblePageNumber < this.total;
            },
            listOfPageNumbers() {
                return Array.from(Array(this.total), (_, i) => i + 1);
            },
            limitedPageNumbers() {
                if (this.total <= this.visible) {
                    return this.listOfPageNumbers;
                }
                if (
                    this.currentPage <
                    this.visible - Math.floor(this.visible / 2) + 1
                ) {
                    return this.listOfPageNumbers.slice(0, this.visible);
                }
                if (
                    this.total - this.currentPage <
                    this.visible - Math.ceil(this.visible / 2) + 1
                ) {
                    return this.listOfPageNumbers.slice(
                        this.total - this.visible,
                    );
                }
                return this.listOfPageNumbers.slice(
                    this.currentPage - Math.ceil(this.visible / 2),
                    this.currentPage + Math.floor(this.visible / 2),
                );
            },
            firstVisiblePageNumber() {
                return this.limitedPageNumbers[0];
            },
            lastVisiblePageNumber() {
                return this.limitedPageNumbers[
                    this.limitedPageNumbers.length - 1
                ];
            },
        },
        methods: {
            go(page) {
                this.$emit('click', page);
            },
            getLinkTo(page) {
                const pageNumber = page.toString();
                if (this.hasRouter) {
                    return {
                        ...this.$route,
                        query: {
                            ...this.$route.query,
                            [this.pageParamName]: page,
                        },
                    };
                } else {
                    return pageNumber;
                }
            },
        },
    };
</script>

<style lang="scss">
    @import '@borngroup/lightswitch-storefront-ui-shared/styles/components/molecules/SfPagination.scss';
</style>
