<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
import { resolveImageSource } from '../utils/resolve-image'

type ImagePlacement = 'auto' | 'left' | 'right' | 'top' | 'bottom'

const props = withDefaults(defineProps<{
  image?: string
  imageFit?: string
  imagePosition?: string
  imagePlacement?: ImagePlacement
}>(), {
  imageFit: 'contain',
  imagePosition: 'center',
  imagePlacement: 'auto',
})

const imagePane = ref<HTMLElement>()
const detectedPlacement = ref<Exclude<ImagePlacement, 'auto'>>('right')
let observedImage: HTMLImageElement | undefined
let observer: MutationObserver | undefined

const placement = computed(() => props.imagePlacement === 'auto'
  ? detectedPlacement.value
  : props.imagePlacement)

function detectPlacement() {
  const image = imagePane.value?.querySelector<HTMLImageElement>('img')
  if (!image)
    return

  if (observedImage !== image) {
    observedImage?.removeEventListener('load', detectPlacement)
    observedImage = image
    observedImage.addEventListener('load', detectPlacement)
  }

  if (image.naturalWidth > 0 && image.naturalHeight > 0)
    detectedPlacement.value = image.naturalWidth / image.naturalHeight >= 1.6 ? 'bottom' : 'right'
}

onMounted(async () => {
  await nextTick()
  detectPlacement()
  if (imagePane.value) {
    observer = new MutationObserver(detectPlacement)
    observer.observe(imagePane.value, { childList: true, subtree: true })
  }
})

onBeforeUnmount(() => {
  observedImage?.removeEventListener('load', detectPlacement)
  observer?.disconnect()
})
</script>

<template>
  <div
    class="slidev-layout easy-layout-image-split easy-layout-image-auto"
    :class="`easy-image-${placement}`"
  >
    <div class="easy-image-content"><slot /></div>
    <div ref="imagePane" class="easy-image-pane">
      <slot name="image">
        <img
          v-if="image"
          :src="resolveImageSource(image)"
          alt=""
          :style="{ objectFit: imageFit, objectPosition: imagePosition }"
        >
      </slot>
    </div>
  </div>
</template>
