<style lang="scss">
    @import "../../../../style/pages/location";
</style>

<script lang="ts">
    import { PUBLIC_LIST_INCREMENT } from '$env/static/public'
    import { page, navigating } from '$app/stores'
    import { scroll, stagger, timeline } from 'motion'
    import dayjs from 'dayjs'
    import relativeTime from 'dayjs/plugin/relativeTime'
    import { quartOut } from '$animations/easings'
    import { getAssetUrlKey } from '$utils/api'
    import { DELAY } from '$utils/constants'
    import { seenLocations } from '$utils/stores'
    import { photoFields } from '$utils/api'
    import { lerp } from 'utils/math'
    import { padZero } from 'utils/string'
    // Components
    import Metas from '$components/Metas.svelte'
    import Image from '$components/atoms/Image.svelte'
    import Button from '$components/atoms/Button/Button.svelte'
    import IconEarth from '$components/atoms/IconEarth.svelte'
    import House from '$components/molecules/House/House.svelte'
    import Pagination from '$components/molecules/Pagination/Pagination.svelte'
    import NewsletterModule from '$components/organisms/NewsletterModule/NewsletterModule.svelte'
    import ShopModule from '$components/organisms/ShopModule/ShopModule.svelte'

    let { data } = $props()

    let photos = $state<any[]>(data.photos)
    let totalPhotos = $state(data.totalPhotos)

    const { location, product = undefined }: { location: any, totalPhotos: number, product: any } = data
    const { params } = $page

    dayjs.extend(relativeTime)

    let introEl = $state<HTMLElement>(undefined)
    let photosListEl = $state<HTMLElement>(undefined)
    let observerPhotos: IntersectionObserver
    let mutationPhotos: MutationObserver
    let currentPage = $state(1)
    let currentPhotosAmount = $derived(photos.length)
    let heroParallax = $state(0)

    const ended = $derived(currentPhotosAmount === totalPhotos)
    const latestPhoto = $derived(photos[0])


    /**
     * Load photos
     */
    /** Load photos helper */
    const loadPhotos = async (page?: number) => {
        const res = await fetch('/api/data', {
            method: 'POST',
            body: `query {
                photos: photo (
                    filter: {
                        location: { slug: { _eq: "${params.location}" }},
                        status: { _eq: "published" },
                    },
                    sort: "-date_created",
                    limit: ${PUBLIC_LIST_INCREMENT},
                    page: ${page},
                ) {
                    ${photoFields}
                }
            }`,
        })
        const { data: { photos } } = await res.json()

        if (photos) {
            // Return new photos
            return photos
        } else {
            new Error('Error while loading new 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(PUBLIC_LIST_INCREMENT)) {
                // Increment the current page
                currentPage++
            }
        }
    }


    $effect(() => {
        // Define location's last seen state
        $seenLocations = JSON.stringify({
            // Add existing values
            ...JSON.parse($seenLocations),
            // Add location ID with current time
            [location.id]: new Date(),
        })

        // 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 })

        // Photos MutationObserver
        if (photos.length) {
            mutationPhotos = new MutationObserver((mutationsList) => {
                // 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))
        }


        /**
         * Add parallax on illustration when scrolling
         */
        scroll(({ y }) => heroParallax = lerp(-15, 10, y.progress), {
            target: introEl,
            offset: ['start end', 'end start'],
        })


        /**
         * Animations
         */
        const animation = timeline([
            // Title word
            ['.location-page__intro .word', {
                y: ['110%', 0],
            }, {
                at: 0.2,
                delay: stagger(0.4)
            }],

            // Illustration
            ['.location-page__hero', {
                scale: [1.06, 1],
                opacity: [0, 1],
            }, {
                at: 0.4,
                duration: 2.4,
            }],

            // Title of
            ['.location-page__intro .of', {
                opacity: [0, 1],
            }, {
                at: 0.95,
                duration: 1.2,
            }],

            // Description
            ['.location-page__description', {
                y: ['10%', 0],
                opacity: [0, 1],
            }, {
                at: 0.9,
                duration: 1.2,
            }]
        ], {
            delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
            defaultOptions: {
                duration: 1.6,
                easing: quartOut,
            },
        })
        animation.stop()

        // Run animation
        requestAnimationFrame(animation.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={latestPhoto ? getAssetUrlKey(latestPhoto.image.id, 'share-image') : null}
/>


<main class="location-page">
    <section bind:this={introEl} class="location-page__intro grid">
        <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">
                    {#if location.credits}
                        <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}
                    {#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 size="medium" url="/locations" text="Change location" class="shadow-small">
                        <IconEarth />
                    </Button>

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

        {#if location?.hero?.id}
            <picture class="location-page__hero" style:--parallax="{heroParallax}%">
                <source media="(min-width: 1200px)" srcset={getAssetUrlKey(location.hero.id, 'hero-large')}>
                <source media="(min-width: 768px)" srcset={getAssetUrlKey(location.hero.id, 'hero-small')}>
                <img
                    src={getAssetUrlKey(location.hero.id, 'hero-mobile')}
                    width={320}
                    height={824}
                    alt="Hero photo of {location.name}"
                    decoding="async"
                />
            </picture>
        {/if}
    </section>

    {#if photos.length}
        <section class="location-page__houses" bind:this={photosListEl} data-sveltekit-noscroll>
            {#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}
                    location={location.name}
                    ratio={width / height}
                    date={date_taken}
                    index={padZero(totalPhotos - index)}
                />
            {/each}
        </section>

        <section class="location-page__next container">
            <Pagination
                ended={ended}
                current={currentPhotosAmount}
                total={totalPhotos}
                onclick={() => !ended && loadMorePhotos()}
            >
                {#if !ended}
                    <p class="more">See more photos</p>
                {:else}
                    <p>You've seen it all!</p>
                {/if}
            </Pagination>

            {#if ended}
                <div class="grid-modules">
                    <div class="container grid">
                        <div class="wrap">
                            {#if location.has_poster}
                                <ShopModule
                                    title="Poster available"
                                    text="Houses of {location.name} is available as a poster on our shop."
                                    images={product.photos_product}
                                    textBottom={null}
                                    buttonText="Buy"
                                    url="/shop/poster-{location.slug}"
                                />
                            {:else}
                                <ShopModule />
                            {/if}
                            <NewsletterModule theme="light" />
                        </div>
                    </div>
                </div>
            {/if}

            {#if location.acknowledgement}
                <div class="acknowledgement">
                    <Image
                        class="flag"
                        id={location.country.flag.id}
                        sizeKey="square-small"
                        width={32} height={32}
                        alt="Flag of {location.country.name}"
                    />
                    <p>{location.acknowledgement}</p>
                </div>
            {/if}
        </section>
    {:else}
        <div class="location-page__message">
            <p>
                No photos available for {location.name}.<br>
                Come back later!
            </p>
        </div>
    {/if}
</main>
