<template>
    <b-row>
        <b-col col cols="12" lg="5">
            <NgPickupPointsSidebar
                :active-item="selectedItem"
                :items="pickupPointsItemsFiltered"
                :pending-request="pendingRequest"
                :user-position="userPosition"
                :enable-search-input-autofocus="enableSearchInputAutofocus"
                @item-selected="handleItemSelected"
                @go-to-my-position="handleGoToMyPositionClick"
                @search-btn-click="handleSearchBtnClick"
            />
        </b-col>
        <b-col class="pl-md-0">
            <NgPickupPointsDetail
                ref="ngPickupPointsDetail"
                :item="selectedItem"
                :items="pickupPointsItems"
                :map-marker-icon-base64="providerIcon"
                :user-position="userPosition"
                @item-selected="handleItemSelected"
                @searched="handleSearched"
            >
                <template v-if="!hideSelectButton" #choose-area>
                    <div class="ng-choose text-center text-lg-right mt-3 mt-lg-0">
                        <b-button variant="primary" class="px-5 font-weight-bold" @click="handleItemChosen()">
                            {{ translations.choose }}
                        </b-button>
                    </div>
                </template>
            </NgPickupPointsDetail>
        </b-col>
    </b-row>
</template>

<script>
import NgPickupPointsSidebar from './NgPickupPointsSidebar.vue'
import NgPickupPointsDetail from './NgPickupPointsDetail.vue'
import * as Utils from '@oxyshop/shop/utils'

export default {
    name: 'NgPickupPointsContext',
    components: {
        NgPickupPointsSidebar,
        NgPickupPointsDetail,
    },
    props: {
        providers: {
            type: Array,
            default: function () {
                return ['store']
            },
        },
        channels: {
            type: Array,
            default: function () {
                return []
            },
        },
        countryCode: {
            type: String,
            default: '',
        },
        hideSelectButton: {
            type: Boolean,
        },
        onlySupplyPoints: {
            type: Boolean,
        },
        enableSearchInputAutofocus: {
            type: Boolean,
        },
    },
    data() {
        return {
            pendingRequest: true,
            selectedItem: {},
            pickupPointsItems: [],
            pickupPointsItemsFiltered: [],
            translations: {
                choose: '',
            },
            providerIcon: '',
            userPosition: {},
        }
    },
    async mounted() {
        try {
            const userPosition = await Utils.Geo.getPosition()
            this.userPosition = {
                latitude: userPosition.coords.latitude,
                longitude: userPosition.coords.longitude,
            }
        } catch (e) {
            /**
             * Fallback to center of Prague
             */
            this.userPosition = {
                latitude: 50.08804,
                longitude: 14.42076,
            }
        }

        this.userPositionOriginal = this.userPosition

        try {
            const items = await this.getApiPickupPoints('pickup-points')
            this.pickupPointsItems = this.sortItemsByDistanceFromCenter(items, this.userPosition)
            this.pickupPointsItemsFiltered = this.pickupPointsItems
        } catch (e) {
            throw new Error('Cant fetch source data from API')
        }

        this.translations = {
            choose: await this.$translations.trans('nextgen.ui.choose'),
        }

        this.providerIcon = await this.getApiPickupPointProviderIcon(this.providers[0])
    },
    methods: {
        handleItemSelected(item, scroll) {
            this.selectedItem = item

            if (!scroll) {
                return
            }

            setTimeout(() => {
                this.scrollToActiveItem()
            }, 0)
        },
        handleItemChosen() {
            this.$emit('item-chosen', this.selectedItem)
        },
        handleSearched(coords) {
            this.pickupPointsItems = this.sortItemsByDistanceFromCenter(this.pickupPointsItems, coords)
            this.userPosition = coords
            this.scrollToActiveItem(true)
        },
        handleGoToMyPositionClick: function () {
            this.userPosition = { ...this.userPositionOriginal }
        },
        handleSearchBtnClick: function () {
            this.$refs.ngPickupPointsDetail.searchBtnClick()
        },
        getApiPickupPoints: async function () {
            const result = []
            const itemsPerPage = 200

            this.pendingRequest = true
            const requestParams = {
                itemsPerPage: itemsPerPage,
                active: true,
                provider: this.providers,
                channels: this.channels,
                countryCode: this.countryCode,
            }

            if (this.onlySupplyPoints) {
                requestParams.supplyPoint = true
            }

            const getDataFromApi = async (url, page) => {
                const response = await this.$http.request({
                    method: this.$http.GET,
                    url: url,
                    params: { ...requestParams, itemsPerPage: 1, page: page },
                })

                return response.data
            }

            /**
             * Mining
             */
            const firstBulk = await getDataFromApi(`/api/v2/shop/pickup-points`, 1)
            const totalPages = Math.ceil(firstBulk['hydra:totalItems'] / itemsPerPage)
            const requestBulk = []
            for (let page = 1; page <= totalPages; page++) {
                requestBulk.push(
                    this.$http.request({
                        method: this.$http.GET,
                        url: `/api/v2/shop/pickup-points`,
                        params: { ...requestParams, page: page },
                    })
                )
            }

            const responses = await this.$http.getClient().all(requestBulk)
            responses.forEach((response) => {
                const items = response.data['hydra:member']
                items.forEach((item) => {
                    result.push(item)
                })
            })

            this.pendingRequest = false

            return result
        },
        getApiPickupPointProviderIcon: async function (provider) {
            const response = await this.$http.request({
                method: this.$http.GET,
                url: `/api/v2/shop/pickup-point-providers/${provider}`,
            })

            return response.data.icon
        },
        sortItemsByDistanceFromCenter(items, center) {
            items.sort((a, b) => {
                const distanceA = Utils.Geo.calcDistanceBetweenCoords(
                    center.latitude,
                    center.longitude,
                    a.coordinates.latitude,
                    a.coordinates.longitude
                )
                const distanceB = Utils.Geo.calcDistanceBetweenCoords(
                    center.latitude,
                    center.longitude,
                    b.coordinates.latitude,
                    b.coordinates.longitude
                )
                return distanceA - distanceB
            })

            return items
        },
        scrollToActiveItem(toTop = false) {
            const activeItem = document.body.querySelector(' .ng-pickup-points-list .list-group-item.active')
            if (!activeItem) {
                return
            }

            let position = activeItem.offsetTop - 100
            if (toTop) {
                position = 0
            }

            activeItem.parentNode.scrollTop = position
        },
    },
}
</script>
