<template>
  <view 
    :id="id" 
    class="nana-collapse-box" 
    :style="{
      display: realOpenState ? '' : 'none',
      height: animDuration > 0 && targetHeight >= 0 ? `${targetHeight}px` : undefined,
      transition: animDuration > 0 ? `height ${animDuration}ms ease-in-out` : undefined,
    }"
  >
    <slot />
  </view>
</template>

<script setup lang="ts">
import { RandomUtils } from '@imengyu/imengyu-utils';
import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue';

export interface CollapseBoxProps {
  /**
   * 开启状态
   */
  open: boolean;
  /**
   * 动画时长(ms)，为0时禁用动画
   * @default 300
   */
  animDuration?: number;
  /**
   * 名称，用于唯一标识
   */
  name?: string;
}

const id = computed(() => `nana-collapse-box-${props.name}-${RandomUtils.genNonDuplicateIDHEX(16)}`);
const props = withDefaults(defineProps<CollapseBoxProps>(), {
  animDuration: 300,
});

const realOpenState = ref(false);
const targetHeight = ref(0);
const instance = getCurrentInstance();
let isAnimWorking = false;

watch(() => props.open, (newVal) => {
  if (props.animDuration <= 0) {
    realOpenState.value = newVal;
    return;
  }
  if (isAnimWorking) 
    return;
  if (newVal) {
    realOpenState.value = true;
    targetHeight.value = -1;
    isAnimWorking = true;
    nextTick(() => {
      uni.createSelectorQuery()
        // #ifdef MP
        .in(instance)
        // #endif
        .select(`#${id.value}`)
        .boundingClientRect(rect => {
          const ref = rect instanceof Array ? rect[0] : rect;
          const height = ref?.height || 500;
          targetHeight.value = 0;
          setTimeout(() => {
            targetHeight.value = height;
            setTimeout(() => {
              isAnimWorking = false;
            }, props.animDuration);
          }, 10);
        })
        .exec()
    })
  } else {
    isAnimWorking = true;
    targetHeight.value = 0;
    setTimeout(() => {
      realOpenState.value = false;
      isAnimWorking = false;
    }, props.animDuration);
  }
});
</script>

<style lang="scss">
.nana-collapse-box {
  overflow: hidden;
  will-change: height;
}
</style>

