<template>
    <div
        v-if="image"
        :class="['strapi-media', { 'fill-space': fillSpace }, `fit-${fit}`]"
        :style="styles"
    >
        <div class="image-sizer">
            <img
                :src="addURLBase(image.url)"
                :srcset="srcset"
                :sizes="sizes"
                :alt="image.alternativeText || ''"
                :width="image.width"
                :height="image.height"
                loading="lazy"
                decoding="async"
            />

            <video
                v-if="video?.url"
                :src="addURLBase(video.url)"
                muted
                autoplay
                playsinline
                loop
            />
        </div>
    </div>
</template>

<script setup>
import { breakpoints } from '@/libs/theme'
import { computed } from 'vue'

const props = defineProps({
    image: Object,
    video: Object,
    aspect: {
        type: [String, Number],
        default: () => -1,
    },
    fillSpace: {
        type: Boolean,
        default: () => false,
    },
    fit: {
        type: String,
        default: () => 'cover',
    },
    mobileSize: {
        type: String,
        default: () => '100vw',
    },
    desktopSize: {
        type: String,
        default: () => '100vw',
    },
})

const addURLBase = (path) => `${import.meta.env.VITE_STRAPI_URL}${path}`

const formats = computed(() => props.image?.formats || {})
const ratio = computed(() => {
    if (!props.image) return 1
    return props.image.height / props.image.width
})
const aspect = computed(() => {
    // calculate if no aspect provided
    if (props.aspect === -1) {
        return ratio.value * 100
    }

    // otherwise, parse provided aspect, handling both 56.25 and 0.5625 style
    const toParse = parseFloat(props.aspect)
    return toParse <= 1 ? toParse * 100 : toParse
})
const styles = computed(() => ({ '--aspect': aspect.value + '%' }))
const srcset = computed(() =>
    Object.values(formats.value)
        .map((f) => `${addURLBase(f.url)} ${f.width}w`)
        .join(', '),
)
const sizes = computed(
    () =>
        `(max-width: ${breakpoints.mobile}) ${props.mobileSize}, ${props.desktopSize}`,
)
</script>

<style lang="scss">
.strapi-media {
    position: relative;
    width: 100%;
    overflow: hidden;

    .image-sizer {
        overflow: hidden;
        padding-bottom: var(--aspect);

        & > * {
            display: block;
            position: absolute;
            height: 100%;
            width: 100%;
            left: 0;
            top: 0;
        }
        .svg {
            background-size: cover;
            background-repeat: no-repeat;
        }
    }

    // fill space
    &.fill-space {
        position: absolute;
        bottom: 0;
        right: 0;
        left: 0;
        top: 0;

        .image-sizer {
            padding-bottom: 0;
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
        }
    }

    // fits
    &.fit-cover .image-sizer > * {
        object-fit: cover;
    }
    &.fit-contain .image-sizer > * {
        object-fit: contain;
    }
}
</style>
