<script setup lang="ts">
import ui from './ui.config'
import {
  Disclosure,
  DisclosureButton,
  DisclosurePanel
} from '@headlessui/vue'
import type {Size, Props} from "./types";
import {twJoin, twMerge} from "tailwind-merge";

defineOptions({
  inheritAttrs: false
})
const attrs = useAttrs()


const props = withDefaults(defineProps<Props>(), {
  defaultOpen: false,
  multiple: true,
  size: "md",
  color: 'gray',
  wrapperClass: ''
})
const getSize = (size?: Size): string => {
  if (size) return twMerge(ui.item.size[size])
  else return ui.item.size[props.size]
}
const buttonClass = computed(() => {
  return twMerge(twJoin(ui.item.color[props.color], ui.ring, ui.item.button))
})
const wrapperClass = computed(() => {
  return twMerge(ui.wrapper, props.wrapperClass)
})

const buttonRefs = ref<{ open: boolean, close: (e: EventTarget) => {} }[]>([])

function closeOthers(currentIndex: number, e: Event) {
  if (!props.items[currentIndex].closeOthers && props.multiple) {
    return
  }

  buttonRefs.value.forEach((button) => {
    if (button.open) {
      button.close(e.target as EventTarget)
    }
  })
}

function onEnter(_el: Element, done: () => void) {
  const el = _el as HTMLElement
  el.style.height = '0'
  el.offsetHeight // Trigger a reflow, flushing the CSS changes
  el.style.height = el.scrollHeight + 'px'

  el.addEventListener('transitionend', done, {once: true})
}

function onBeforeLeave(_el: Element) {
  const el = _el as HTMLElement
  el.style.height = el.scrollHeight + 'px'
  el.offsetHeight // Trigger a reflow, flushing the CSS changes
}

function onAfterEnter(_el: Element) {
  const el = _el as HTMLElement
  el.style.height = 'auto'
}

function onLeave(_el: Element, done: () => void) {
  const el = _el as HTMLElement
  el.style.height = '0'

  el.addEventListener('transitionend', done, {once: true})
}

</script>

<template>
  <div :class="wrapperClass">
    <Disclosure
      v-for="(item, index) in items"
      v-slot="{ open, close }"
      :key="index"
      as="div"
      :class="ui.item.accordion"
      :default-open="defaultOpen || item.defaultOpen"
    >
      <DisclosureButton
        :ref="() => buttonRefs[index] = { open, close }"
        :disabled="item.disabled"
        as="template"
        @click="closeOthers(index, $event)"
        @keydown.enter="closeOthers(index, $event)"
        @keydown.space="closeOthers(index, $event)"
      >
        <slot
          :item="item"
          :index="index"
          :open="open"
          :close="close"
        >
          <button
            :class="[getSize(item?.size), buttonClass]"
            v-bind="{...attrs}"
          >
            <span>{{ item.label }}</span>
            <a-icon-chevron-down
              :arrow-attrs="{class: 'stroke-deepblue-900'}"
              width="16px"
              height="16px"
              :class="[{'rotate-180': !open, }, ui.item.icon ]"
            />
          </button>
        </slot>
      </DisclosureButton>
      <Transition
        v-bind="ui.transition"
        @enter="onEnter"
        @after-enter="onAfterEnter"
        @before-leave="onBeforeLeave"
        @leave="onLeave"
      >
        <div v-show="open">
          <DisclosurePanel static>
            <div :class="ui.item.content">
              <slot
                :name="item.slot || 'item'"
                :item="item"
                :index="index"
                :open="open"
                :close="close"
              >
                {{ item.content }}
              </slot>
            </div>
          </DisclosurePanel>
        </div>
      </Transition>
    </Disclosure>
  </div>
</template>

<style scoped>

</style>
