<template>
    <div>
        <product-filter
            :items="products"
            :filters="filters"
            :loading="loading"
            :follow-links="followLinks"
            @update-ajax="updateAjax"
        ></product-filter>

        <slot name="products" />

        <slot name="pagination" />

        <loading-spinner :loading="loading" loading-text="Loading Products"></loading-spinner>
    </div>
</template>

<script>
import Vue from 'vue'
import axios from 'axios'
import productFilter from './product_filter'

export default {
    name: 'BrowsePage',
    components: {
        productFilter,
    },
    props: {
        setProducts: {
            type: [Object, Array, Boolean],
            default(rawProps) {
                return []
            },
        },
        setFilters: {
            type: [Object, Array, Boolean],
            default(rawProps) {
                return []
            },
        },
    },
    data() {
        return {
            products: [],
            filters: [],
            previousURL: window.location.href,
            loading: false,
        }
    },
    created() {
        this.products = this.setProducts
        this.filters = this.setFilters
    },
    mounted() {
        window.addEventListener('popstate', this.handlePopState)
    },
    beforeDestroy() {
        window.removeEventListener('popstate', this.handlePopState)
        if (this._abortController) this._abortController.abort()
        if (this._productsVm) this._productsVm.$destroy()
        if (this._paginationVm) this._paginationVm.$destroy()
    },
    computed: {
        followLinks() {
            return !this.filters?.selections?.length
        },
    },
    methods: {
        handlePopState(e) {
            const url = e.state && e.state.url ? e.state.url : window.location.href
            this.updateAjax(url, true)
        },

        updateAjax(url, usedPopState) {
            if (!url) return

            if (this._abortController) {
                this._abortController.abort()
            }
            this._abortController = new AbortController()

            this.loading = true

            const productsContainer = this.$el.querySelector('.productListWrap')
            const paginationContainer = this.$el.querySelector('.paginationSlot')

            if (productsContainer) {
                productsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' })
            }

            axios.get(this.enableAjaxURL(url), { signal: this._abortController.signal, timeout: 15000 })
                .then((response) => {
                    const data = response.data || {}

                    if (productsContainer && typeof data.product_list_html === 'string') {
                        this.swapHtmlAndMount(productsContainer, data.product_list_html, '_productsVm')
                    }

                    if (paginationContainer && typeof data.pagination_html === 'string') {
                        this.swapHtmlAndMount(paginationContainer, data.pagination_html, '_paginationVm')
                    }

                    if (data.filters) {
                        this.filters = data.filters
                    }
                    if (data.products) {
                        this.products = data.products
                    }

                    if (window.lazyLoadInstance && typeof window.lazyLoadInstance.update === 'function') {
                        window.lazyLoadInstance.update()
                    }

                    if (data.page_meta && data.page_meta.title) {
                        document.title = data.page_meta.title
                    }

                    if (!usedPopState) {
                        window.history.pushState({ url }, '', url)
                    }

                    this.previousURL = url
                })
                .catch((error) => {
                    if (axios.isCancel(error)) return
                    window.location.href = url
                })
                .finally(() => {
                    this.loading = false
                })
        },

        swapHtmlAndMount(container, html, vmKey) {
            if (this[vmKey]) {
                this[vmKey].$destroy()
                this[vmKey] = null
            }

            container.innerHTML = html

            const root = container.firstElementChild
            if (!root) return

            // Match the root Vue instance's delimiters (set in main-app.js) so any stray `{{ }}`
            // in Twig-rendered product copy isn't treated as a Vue placeholder.
            this[vmKey] = new Vue({
                delimiters: ['[%', '%]'],
                store: this.$store,
            }).$mount(root)
        },

        // Workaround for .htaccess breaking POST-style/AJAX requests — flag the URL so the controller returns JSON.
        enableAjaxURL(url) {
            const parts = url.split('?')
            const query = parts.length > 1
                ? '?' + parts[1] + '&ajax_request=true'
                : '?ajax_request=true'
            return parts[0] + query
        },

        relFollow(allowFollow) {
            if (!allowFollow) {
                return 'nofollow'
            }

            return ''
        },
    },
}
</script>
