<script lang="ts">
    import { navigating, page } from '$app/stores'
    import { onMount } from 'svelte'
    import anime from 'animejs'
    import type { AnimeTimelineInstance } from 'animejs'
    import dayjs from 'dayjs'
    import relativeTime from 'dayjs/plugin/relativeTime.js'
    import { getAssetUrlKey } from '$utils/helpers'
    import { fetchAPI } from '$utils/api'
    import { DURATION } from '$utils/contants'
    import { photoFields } from '.'
    // Components
    import Metas from '$components/Metas.svelte'
    import PageTransition from '$components/PageTransition.svelte'
    import Button from '$components/atoms/Button.svelte'
    import IconEarth from '$components/atoms/IconEarth.svelte'
    import House from '$components/molecules/House.svelte'
    import NewsletterModule from '$components/organisms/NewsletterModule.svelte'

    export let location: any
    export let photos: any[]
    export let totalPhotos: number

    dayjs.extend(relativeTime)

    const { params } = $page

    let introEl: HTMLElement
    let photosListEl: HTMLElement
    let scrollY: number
    let observerPhotos: IntersectionObserver
    let mutationPhotos: MutationObserver
    let currentPage = 1
    let ended: boolean
    let currentPhotosAmount: number
    let illustrationOffsetY = 0

    $: latestPhoto = photos[0]
    $: currentPhotosAmount = photos.length
    $: ended = currentPhotosAmount === totalPhotos
    $: hasIllustration = location.illustration_desktop && location.illustration_desktop_2x && location.illustration_mobile


    /**
     * Load photos
     */
    // Load more photos from CTA
    const loadMorePhotos = async () => {
        // Append more photos from API
        const newPhotos: any = await loadPhotos(currentPage + 1)

        if (newPhotos) {
            photos = [...photos, ...newPhotos]

            // Define actions if the number of new photos is the expected ones
            if (newPhotos.length === Number(import.meta.env.VITE_LIST_INCREMENT)) {
                // Increment the current page
                currentPage++
            }

            // Increment the currently visible amount of photos
            currentPhotosAmount += newPhotos.length
        }
    }

    // [function] Load photos helper
    const loadPhotos = async (page?: number) => {
        const res = fetchAPI(`
            query {
                photos: photo (
                    filter: {
                        location: { slug: { _eq: "${params.location}" }},
                        status: { _eq: "published" },
                    },
                    sort: "-date_created",
                    limit: ${import.meta.env.VITE_LIST_INCREMENT},
                    page: ${page},
                ) {
                    ${photoFields}
                }
            }
        `)
        const { data: { photos }} = await res

        if (photos) {
            // Return new photos
            return photos
        } else {
            throw new Error('Error while loading new photos')
        }
    }


    /**
     * Add parallax on illustration when scrolling
     */
    $: if (scrollY && scrollY < introEl.offsetHeight) {
        illustrationOffsetY = scrollY * 0.1
    }


    onMount(() => {
        // Photos IntersectionObserver
        observerPhotos = new IntersectionObserver(entries => {
            entries.forEach(({ isIntersecting, target }: IntersectionObserverEntry) => {
                target.classList.toggle('is-visible', isIntersecting)

                // Run effect once
                isIntersecting && observerPhotos.unobserve(target)
            })
        }, {
            threshold: 0.3,
            rootMargin: '0px 0px 0px'
        })

        // Photos MutationObserver
        mutationPhotos = new MutationObserver((mutationsList, observer) => {
            // When adding new childs
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    // Observe new items
                    Array.from(mutation.addedNodes)
                        .filter(item => item.nodeType === Node.ELEMENT_NODE)
                        .forEach((item: HTMLElement) => observerPhotos.observe(item))
                }
            }
        })
        mutationPhotos.observe(photosListEl, {
            childList: true,
        })

        // Observe existing elements
        const existingPhotos = photosListEl.querySelectorAll('.house')
        existingPhotos.forEach(el => observerPhotos.observe(el))


        /**
         * Animations
         */
        // Transition in
        const timeline: AnimeTimelineInstance = anime.timeline({
            duration: 1600,
            easing: 'easeOutQuart',
            autoplay: false,
        })

        // Title word
        timeline.add({
            targets: '.location-page__intro .word',
            translateY: ['110%', 0],
            delay: anime.stagger(200)
        }, 200 + ($navigating ? DURATION.PAGE_IN : 0))

        // Illustration
        timeline.add({
            targets: '.location-page__illustration',
            scale: [1.06, 1],
            opacity: [0, 1],
            duration: 2400,
        }, 400 + ($navigating ? DURATION.PAGE_IN : 0))

        // Title of
        timeline.add({
            targets: '.location-page__intro .of',
            opacity: [0, 1],
            duration: 1200,
        }, 1050 + ($navigating ? DURATION.PAGE_IN : 0))

        // Description
        timeline.add({
            targets: '.location-page__description',
            translateY: ['10%', 0],
            opacity: [0, 1],
        }, 900 + ($navigating ? DURATION.PAGE_IN : 0))

        requestAnimationFrame(timeline.play)


        // Destroy
        return () => {
            observerPhotos && observerPhotos.disconnect()
            mutationPhotos && mutationPhotos.disconnect()
        }
    })
</script>

<Metas
    title="Houses Of {location.name}"
    description="Discover {totalPhotos} beautiful homes from {location.name}, {location.country.name}"
    image={getAssetUrlKey(latestPhoto.image.id, 'share-image')}
/>

<svelte:window bind:scrollY />


<PageTransition name="location-page">
    <section class="location-page__intro grid" bind:this={introEl}>
        <h1 class="title" class:is-short={location.name.length <= 4}>
            <span class="housesof mask">
                <strong class="word">Houses</strong>
                <span class="of">of</span>
            </span>
            <strong class="city mask">
                <span class="word">{location.name}</span>
            </strong>
        </h1>

        <div class="location-page__description grid">
            <div class="wrap">
                <div class="text-medium">
                    Houses of {location.name} {location.description ?? 'has no description yet'}
                </div>
                <div class="info">
                    <p class="text-label">
                        Photos by
                        {#each location.credits as { credit_id: { name, website }}}
                            {#if website}
                                <a href={website} target="_blank" rel="noopener external">
                                    {name}
                                </a>
                            {:else}
                                <span>{name}</span>
                            {/if}
                        {/each}
                    </p>
                    {#if latestPhoto}
                        &middot;
                        <p class="text-label" title={dayjs(latestPhoto.date_created).format('DD/MM/YYYY, hh:mm')}>
                            Updated <time datetime={dayjs(latestPhoto.date_created).format('YYYY-MM-DD')}>
                                {dayjs().to(dayjs(latestPhoto.date_created))}
                            </time>
                        </p>
                    {/if}
                </div>

                <div class="ctas">
                    <Button url="/locations" text="Change location" class="shadow-small">
                        <IconEarth />
                    </Button>

                    {#if location.has_poster}
                        <Button url="/shop/poster-{location.slug}" text="Buy the poster" color="pinklight" class="shadow-small">
                            <!-- <IconEarth /> -->
                        </Button>
                    {/if}
                </div>
            </div>
        </div>

        {#if hasIllustration}
            <picture class="location-page__illustration" style="--parallax-y: {illustrationOffsetY}px;">
                <source media="(min-width: 1200px)" srcset={getAssetUrlKey(location.illustration_desktop_2x.id, 'illustration-desktop-2x')}>
                <source media="(min-width: 768px)" srcset={getAssetUrlKey(location.illustration_desktop.id, 'illustration-desktop-1x')}>
                <img
                    src={getAssetUrlKey(location.illustration_mobile.id, 'illustration-mobile')}
                    width={320}
                    height={824}
                    alt="Illustration for {location.name}"
                    loading="lazy"
                />
            </picture>
        {/if}
    </section>

    {#if photos.length}
        <section class="location-page__houses grid" bind:this={photosListEl}>
            {#each photos as { title, image: { id, title: alt, width, height }, slug, city, date_taken }, index}
                <House
                    {title}
                    photoId={id}
                    photoAlt={alt}
                    url="/{params.country}/{params.location}/{slug}"
                    {city}
                    ratio={width / height}
                    date={date_taken}
                    index={(totalPhotos - index < 10) ? '0' : ''}{totalPhotos - index}
                />
            {/each}
        </section>

        <section class="location-page__next">
            <div class="container">
                <div class="pagination" role="button"
                    on:click={!ended && loadMorePhotos} disabled={ended ? ended : undefined}
                    on:keydown={({ key, target }) => key === 'Enter' && target.click()}
                    tabindex="0"
                >
                    <div class="pagination__progress">
                        <span class="current">{currentPhotosAmount}</span>
                        <span>/</span>
                        <span class="total">{totalPhotos}</span>

                        {#if !ended}
                            <p class="pagination__more">See more photos</p>
                        {:else}
                            <p class="pagination__message">You've seen it all!</p>
                        {/if}
                    </div>
                </div>

                {#if ended}
                    <NewsletterModule theme="light" />
                {/if}
            </div>
        </section>
    {:else}
        <div class="location-page__message">
            <p>
                No photos available for {location.name}.<br>
                Come back later!
            </p>
        </div>
    {/if}
</PageTransition>