<template>
  <q-dialog
    v-model="modelValue"
    transition-show="slide-up"
    transition-hide="slide-down"
    position="bottom"
    :persistent="loading"
    >
    <q-card
      ref="cardRef"
      class="fix-card-width column no-scroll no-wrap q-px-none overflow-hidden relative-position"
      style="
        border-top-left-radius: var(--top-radius) !important;
        border-top-right-radius: var(--top-radius) !important;
        max-height: calc(100vh - 48px - var(--tg-content-safe-area-inset-top) - var(--tg-safe-area-inset-top));
      "
      >
      <div
        ref="cardHeaderRef"
        class="flex items-center no-wrap justify-between w100 q-my-none q-pa-md"
        >
        <q-resize-observer @resize="onHeaderResize" />
        <div class="column q-mx-xs">
          <span class="text-bold">
            {{ $t(title) }}
          </span>
          <span v-if="caption" class="text-grey text-caption">
            {{ $t(caption) }}
          </span>
        </div>
        <q-space/>
        <div
          v-if="!loading"
          class="flex items-center justify-between no-wrap" 
          >
          <slot name="btn-slot">
            <q-btn
              icon="mdi-close"
              dense flat round 
              v-close-popup
            />
          </slot>
        </div>
      </div>

      <div class="q-px-none q-ma-none">
        <pn-shadow-scroll
          :height="bodyHeight"
          :bottomOffset
          :topOffset
          >
          <div class="q-pa-none q-ma-none">
            <q-resize-observer @resize="onInnerBodyResize" />
            <slot />
          </div>
        </pn-shadow-scroll>
      </div>

      <div v-if="hasFooter" class="absolute-bottom">
        <q-resize-observer @resize="onFooterResize" />
        <div class="q-pa-md">
          <slot name="footer" />
        </div>
        <div :style="{ height: tgInsetBottom + 'px' }" />
      </div>
    </q-card>
  </q-dialog>
</template>

<script setup lang="ts">
  import { ref, computed, onMounted, onUnmounted, useSlots } from 'vue'

  const modelValue = defineModel<boolean>({ required: true })
  const props = withDefaults(defineProps<{
    title: string
    caption?: string
    maximized?: boolean
    loading?: boolean
  }>(), { 
    maximized: true,
    loading: false
  })

  const slots = useSlots()
  const cardRef = ref()

  const headerHeight = ref(0)
  const footerHeight = ref(0)
  const bodyInnerHeight = ref(0)
  const tgInsetBottom = ref(0)
  const topOffset = 16

  const windowHeight = ref(window.innerHeight)

  const hasFooter = computed(() => !!slots['footer'])
  const bottomOffset = computed(() => hasFooter.value ? footerHeight.value : tgInsetBottom.value)

  const bodyHeight = computed(() => {
    // hack for update computed params on window resize
    const _trigger = windowHeight.value //eslint-disable-line 
    const el = cardRef.value?.$el
    if (!el) return 0

    const maxH = parseFloat(window.getComputedStyle(el).maxHeight) || 0

    return props.maximized
       ? maxH - headerHeight.value
       : Math.min(
          bodyInnerHeight.value + topOffset + (hasFooter.value ? footerHeight.value : 0),
          maxH - headerHeight.value
        )
  })

  interface SizeParams { height: number; width: number }
  const onHeaderResize = (size: SizeParams) => headerHeight.value = size.height
  const onFooterResize = (size: SizeParams) => footerHeight.value = hasFooter.value ? size.height : 0
  const onInnerBodyResize = (size: SizeParams) => bodyInnerHeight.value = size.height + 32

  const handleWindowResize = () => {
    windowHeight.value = window.innerHeight
  }

  const getTgInsetBottom = () => {
    const value = getComputedStyle(document.documentElement)
      .getPropertyValue('--tg-safe-area-inset-bottom')
      .trim()
    
    tgInsetBottom.value = parseFloat(value) || 0
  }

  onMounted(() => getTgInsetBottom())
  
  onMounted(() => {
    window.addEventListener('resize', handleWindowResize)
    getTgInsetBottom()
  })

  onUnmounted(() => window.removeEventListener('resize', handleWindowResize))

</script>

<style scoped>
  .fix-card-width {
    width: var(--body-width) !important;
  }
</style>
