<template lang="pug">
.page--single.f-col.between
    gallery(v-if="activeGalleryIndex >= 0" :activeImageIndex="activeImageIndex" :images="imagesInGallery" @close="closeGallery")

    article.w-max(v-if="!singlePost || loading")
        header
            p loading...
    article(v-else).w-max.f-grow.shadow
        header
            //- breadcrumb links at top of page, needs link routing
            breadcrumb(:type="type" :post="singlePost")
            
            h1.t-b  {{ singlePost.title }}
            //- p(v-if="singlePost.categories") categories: {{ singlePost.categories }}
            //- p(v-if="singlePost.type") type: {{ singlePost.type }}
            //- p(v-if="singlePost.subtypes") subtypes: {{ singlePost.subtypes }}

            .date-info(v-if="['exhibition', 'event'].includes(type)")
                p start: {{ dateFrom(singlePost.start, type == 'event') }}
                p end: {{ dateFrom(singlePost.end, type == 'event') }}

        //- WP main content
        section.content(v-html="singlePost.content")

        //- related artists section for episodes
        section(v-if="type === 'episode' && post" :post="post")
            h2.t-up featured in this episode
            ul
                li.f-row.between(v-for="artist in p2pPostsByType['artist']")
                    card(:content="artist" type="artist" :wide="true" :hide-type="true")
            
        credits(v-if="type === 'episode' && singlePost" :post="singlePost")
        
        //- end of article icon
        footer.f-col
            img(src="../star.svg")

    sidebar(v-if="sidebar" :type="`${type}`" layout="single" :related="p2pPostsByType")
</template>

<script>
import { mapGetters, mapState } from 'vuex'
import card from '@/components/card.vue'
import sidebar from '@/components/sidebars/sidebar'
import gallery from '@/components/gallery/'
import credits from '@/components/credits'
import breadcrumb from '@/components/breadcrumb'

import { postTypeGetters, scrollTop, heroUtils } from './mixin-post-types'

import { postTypes, sortTypes, convertTitleCase, dePluralize, typeFromRoute } from '@/utils/helpers'

const TIMEOUT = 1

export default {
    components: { sidebar, gallery, credits, card, breadcrumb },
    props: {
        sidebar: { type: Boolean },
        id: { type: Number },
    },
    mixins: [postTypeGetters, scrollTop, heroUtils],
    data() {
        return {
            // Gallery control
            activeGalleryIndex: -1,
            activeImageID: -1,
            loading: true
        }
    },
    computed: {
        type() {
            // Checks for type and fixes Episodes route edge case
            return typeFromRoute(this.$route)
        },
        /**
         * We get the actual post data using the slug
         * Careful with name collisions with vuex helpers
         */
        singlePost() {
            if (!this[this.type]) return
            const type = dePluralize(this.type)

            // State not a getter!
            const singleOfTypeFromState =
                this[this.type][`single${convertTitleCase(type)}`]

            if (!singleOfTypeFromState) return

            return singleOfTypeFromState
        },

        idsForGallery() {
            if (!this.singlePost || this.activeGalleryIndex < 0) return []
            return this.singlePost.galleries[this.activeGalleryIndex].ids
        },
        /**
         * We need a convenient way to get all the images
         * broken down by gallery. We use the active gallery
         * image IDs to create a map. We match the ID to the
         * image size and url information returned by singlePost.attached
         */
        imagesInGallery() {
            if (!this.activeGalleryIndex < 0) return {}

            return this.idsForGallery.reduce((imageMap, id) => {
                imageMap[id] = this.singlePost.attached[parseInt(id)]
                return imageMap
            }, {})
        },
        activeImageIndex() {
            return Object.keys(this.imagesInGallery).indexOf(
                this.activeImageID.toString(),
            )
        },
        p2pPostsByType() {
            return this.singlePost
                ? Object.values(this.singlePost.relatedto).reduce(
                      (byType, relatedPost) => {
                          if (!byType[relatedPost.type])
                              byType[relatedPost.type] = []
                          byType[relatedPost.type].push(relatedPost)
                          return byType
                      },
                      {},
                  )
                : {}
        },
    },
    methods: {
        /**
         * We set the active gallery to the index.
         * Everything kicks off when activeGallery
         * is set. We also need to set the activeImageID
         * to the image clicked
         * @param {string} imageInfo
         */
        openGallery(imageInfo) {
            const byIndex = this.singlePost.galleries.reduce(
                (byIndex, gallery, index) => {
                    byIndex[index] = gallery.ids
                    return byIndex
                },
                {},
            )
            let matchingIndex = 0
            Object.keys(byIndex).forEach(galleryIndex => {
                if (
                    byIndex[galleryIndex].includes(
                        parseInt(imageInfo.dataset.id),
                    )
                )
                    matchingIndex = galleryIndex
            })
            this.activeGalleryIndex = matchingIndex
            this.activeImageID = imageInfo.dataset.id
                ? parseInt(imageInfo.dataset.id)
                : parseInt(imageInfo.className.split('-').pop())
        },
        closeGallery() {
            this.activeGalleryIndex = this.activeImageID = -1
        },
        // _setHeroInfo(post) {} from mixin
        // _clearHero(store) {} from mixin
        /**
         * Everytime the posts object changes
         * we use this to set a new HERO
         * in vuex
         * @param {object} posts
         */
        checkAndSetHero(post) {
            this._clearHero(this.$store)
            if (!post) return console.warn(`no post found`)
            this.$store.commit('SET_HERO', this._setHeroInfo(post))
        },

        /**
         * Date Object from unix strings from db
         */
        dateFrom(unix, includeTime) {
            const d = new Date(parseInt(unix) * 1000)
            return includeTime ? d.toLocaleString('en-US', { timeZone: 'UTC' }) : d.toLocaleDateString('en-US')
        },

        async loadPostData() {
            /**
             * Conditionally load based on post type
             * which is derived from the route
             */
            // modules are NOT plural because module key
            if (!this.$store.state[this.type]) return
            let allPostsOfType = this.$store.state[this.type].all

            /**
             * Load posts if they're not already in state
             */
            // Find the single post from api if it's not already in state
            // Then add it to our list
            let singlePostData = allPostsOfType.filter(
                post => post.slug == this.$route.params.slug,
            )[0]

            // Look if it exists before you try and load everything!
            if(!singlePostData) {
                const res = await this.$store.dispatch(`getAll${convertTitleCase(this.type)}s`, { sortType: null, params: null})
                allPostsOfType = res
                singlePostData = allPostsOfType.filter(
                    post => post.slug == this.$route.params.slug,
                )[0]
            }

            if (!singlePostData) return console.error('could not get single post data...')
            
            // NOT plural
            this.checkAndSetHero(singlePostData)
            await this.$store.dispatch(
                `getSingle${convertTitleCase(this.type)}`,
                singlePostData.id,
            )
            this.loading = false
        },
    },
    watch: {
        $route(to, from) {
            // Only load post data when
            //  navigating TO a single page
            const path = to.fullPath.split('/').filter(p => p)
            const hasSort = path.filter(fragment => Object.values(sortTypes).includes(fragment))
            console.log('hasSort :', hasSort)
            console.log('path :', path)
            if (path.length <= 2 && postTypes.includes(path[0]) && hasSort.length < 1) {
                this._clearHero(this.$store)
                this.loadPostData()
            }
        },
    },
    created() {
       this.loadPostData()
    },
}
</script>

<style lang="postcss">
// prettier-ignore
@import '../sss/variables.sss'
@import '../sss/theme.sss'
.page--single
    article
        background-color: white
        padding: $ms-0
        h1
            color: $cia_black
            margin: 0 0 $ms--3 0
        > ul
            /* grid-gap: $ms-0 */
            list-style: none
            /* change to a 1/3 width of the article*/
            img.feature
                width: 20em 
            li
        /* wp-block-embed youtube link */
        .wp-block-embed, .is-type-video
            position: relative
            width: 100% 
            padding-bottom: 56.25% 
            &__wrapper
                display: contents
            /* TBD if kept */
            figcaption 
                position: absolute
                top: 39%
                margin: 0 3em 0
                color: aqua
                backdrop-filter: brightness(0.5)

        /* iframe container 16:9 */
        .iframe-container 
            position: relative
            width: 100% 
            padding-bottom: 56.25% 

        /* iframe container portrait */
        .iframe-container-v
            position: relative
            width: 100%
            height: 100%
            padding-bottom: 125%
            
        iframe 
            position: absolute 
            top: 0px 
            left: 0px 
            width: 100% 
            height: 100%
        /* separator styles */
        * hr
            margin: $ms-2 auto
            &.is-style
                &-default
                    height: 1px
                    width: 15vw
                &-wide
                    height: 3px
                    width: 50vw
                &-dots::before
                    outline-style: none
                    font-weight: bolder
                    letter-spacing: $ms-8
                    padding-left: $ms-8
        /* margin to indent marker */
        li
            margin: 0 0 $ms--2 $ms-4

        breadcrumb
            h5
                /* color: yellow */
                color: $cia_red
                /* font-weight: 400 */
                /* padding: $ms--6 0 */
        
        //- end of article icon
        footer
            padding: $ms-6 0
            img
                height: $ms-3
                width: $ms-3

        
@media (min-width: $medium)
    .page--single.f-col
        flex-direction: row
</style>
