<template>
    <div class="pagination d-flex justify-content-between">
        <div class="pagination__container">
            <div
                v-for="(page, index) in pagesToDisplay"
                :key="`page-${index + 1}`"
                :class="{'pagination__item-highlight': page === currentPage}"
                class="pagination__item-container">
                <div
                    @click="changeCurrentPage(page)"
                    :class="page === '...' ? 'pagination__ellipsis-item' : 'pagination__item'">
                    <i
                        v-if="isLastPageLoading(index)"
                        class="fas fa-spinner fa-spin"
                        aria-hidden="true"
                        title="Loading total pages..." />
                    <span v-else>{{ page }}</span>
                </div>
            </div>
        </div>

        <div
            v-if="goToInput"
            class="d-flex ml-3">
            <div class="align-self-center px-2">
                Go to page:
            </div>

            <input
                aria-label="text input go to page number"
                v-model.number="goToInputText"
                type="number"
                class="form-control go-to-input mr-2"
                @keyup.enter="changeCurrentPage(goToInputText)">

            <button
                title="go to page"
                class="btn btn-link form-control d-inline-block go-to-button"
                @click="changeCurrentPage(goToInputText)">
                <i class="fa fa-chevron-right" aria-hidden="true" />
            </button>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        currentPage: {
            type: Number,
            default: 10,
        },
        recordsPerPage: {
            type: Number,
            default: 10,
        },
        count: {
            type: Number,
            default: 0,
        },
        goToInput: {
            type: Boolean,
            default: true,
        },
        // buttons on either side of selected page (in the middle range)
        neighbors: {
            type: Number,
            default: 1,
        },
        // buttons to the right of the first page, buttons to the left of the last page
        endItemsRange: {
            type: Number,
            default: 2,
        },
        countLoading: {
            type: Boolean,
            default: false,
        },
    },
    data() {
        return {
            goToInputText: '',
        }
    },
    computed: {
        pages() {
            if (this.countLoading && this.count === 0) {
                return this.getLoadingPageRange()
            }
            return Math.ceil(this.count / this.recordsPerPage) || 1
        },
        pagesToDisplay() {
            const pagesForDisplay = [];
            for (let page = 1; page <= this.pages; page++) {
                if (this.shouldBeDisplayed(page)) {
                    pagesForDisplay.push(page)
                }
                if (!this.shouldBeDisplayed(page) && this.shouldBeDisplayed(page - 1)) {
                    pagesForDisplay.push('...')
                }
            }
            return pagesForDisplay
        },
    },
    methods: {
        getLoadingPageRange() {
            return Math.max(this.currentPage + 10, 20)
        },
        changeCurrentPage(page) {
            if (typeof page !== 'number') return
            let adjustedPage = page
            if (page < 1) adjustedPage = 1
            if (page > this.pages) adjustedPage = this.pages
            this.goToInputText = ''
            this.$emit('change', adjustedPage)
        },
        shouldBeDisplayed(page) {
            const isBeginningOrEnd = this.currentPage === this.pages || this.currentPage === 1
            const isInStartOrEndRange = Math.abs(this.currentPage - page) <= this.endItemsRange
            const isInMiddleRange = Math.abs(this.currentPage - page) <= this.neighbors
            const isInRange = isBeginningOrEnd ? isInStartOrEndRange : isInMiddleRange
            if (page === 1
                || page === this.pages
                || isInRange
            ) return true
            return false
        },
        isLastPageLoading(index) {
            if (!this.countLoading) return false
            const isLastItem = index === this.pagesToDisplay.length - 1
            const isPageNumber = typeof this.pagesToDisplay[index] === 'number'
            return isLastItem && isPageNumber
        },
    },
}
</script>
