<template>
  <view 
    :class="[
      'nana-popup',
      position,
      showAnimState ? 'show' : '',
      mask ? 'stop' : '',
      mask ? (show2 ? 'show2' : '') : 'no-mask',
    ]"
    :style="{
      ...selectStyleType(position, 'bottom', {
        center: {
          justifyContent: 'center',
          alignItems: 'center',
        },
        top: {
          justifyContent: 'flex-start',
          alignItems: 'center',
        },
        bottom: {
          justifyContent: 'flex-end',
          alignItems: 'center',
        },
        left: {
          alignItems: 'flex-start',
          justifyContent: 'center',
        },
        right: {
          alignItems: 'flex-end',
          justifyContent: 'center',
        },
      }),
      top: inset[0] ? `${themeContext.resolveThemeSize(inset[0])}` : undefined,
      right: inset[1] ? `${themeContext.resolveThemeSize(inset[1])}` : undefined,
      bottom: inset[2] ? `${themeContext.resolveThemeSize(inset[2])}` : undefined,
      left: inset[3] ? `${themeContext.resolveThemeSize(inset[3])}` : undefined,
    }"
  >
    <view 
      class="nana-popup-mask" 
      :style="{
        backgroundColor: mask ? themeContext.resolveThemeColor(maskColor) : '',
        transitionDuration: `${duration}ms`,
      }"
      @mousedown.stop="handleClose"
      @touchstart.stop="handleClose"
      @click.stop="handleClose"
    >  
    </view>
    <view 
      v-if="show2"
      :class="[ 'nana-popup-content', position] "
      :style="{
        ...selectStyleType(position, 'bottom', {
          center: {
            flexDirection: 'row',
            borderRadius: radius,
          },
          top: {
            borderBottomLeftRadius: radius,
            borderBottomRightRadius: radius,
            width: '100%',
            minHeight: dialogSize,
          },
          bottom: {
            borderTopLeftRadius: radius,
            borderTopRightRadius: radius,
            width: '100%',
            minHeight: dialogSize,
          },
          left: {
            borderTopRightRadius: radius,
            borderBottomRightRadius: radius,
            height: '100%',
            minWidth: dialogSize,
          },
          right: {
            borderTopLeftRadius: radius,
            borderBottomLeftRadius: radius,
            height: '100%',
            minWidth: dialogSize,
          },
        }),
        backgroundColor: themeContext.resolveThemeColor(backgroundColor),
        margin: `${themeContext.resolveThemeSize(margin[0])} ${themeContext.resolveThemeSize(margin[1])} ${themeContext.resolveThemeSize(margin[2])} ${themeContext.resolveThemeSize(margin[3])}`,
        ...innerStyle,
      }"
      @click.stop
    >
      <SafeAreaPadding
        :top="safeArea && (position === 'top' || position === 'left' || position === 'right')"
        :bottom="safeArea && (position === 'bottom' || position === 'left' || position === 'right')"
      >
        <PopupTitle 
          v-if="position !== 'top'"
          :closeable="closeable"
          :closeIcon="closeIcon"
          :closeIconSize="closeIconSize"
          :closeIconPosition="closeIconPosition"
          :top="true"
          @close="doClose"
        />
        <slot />
        <PopupTitle
          v-if="position === 'top'"
          :closeable="closeable"
          :closeIcon="closeIcon"
          :closeIconSize="closeIconSize"
          :closeIconPosition="closeIconPosition"
          @close="doClose"
        />
      </SafeAreaPadding>
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useTheme, type ViewStyle } from '../theme/ThemeDefine';
import { selectStyleType } from '../theme/ThemeTools';
import { SimpleDelay } from '@imengyu/imengyu-utils';
import PopupTitle from './PopupTitle.vue';
import SafeAreaPadding from '../layout/space/SafeAreaPadding.vue';

/**
 * Popup 的显示位置
 */
export type PopupPosition = 'center'|'top'|'bottom'|'left'|'right';
/**
 * Popup 关闭按钮显示位置
 */
export type PopupCloseButtonPosition = 'left'|'right';

/**
 * Popup 组件属性
 */
export interface PopupProps {
  /**
   * 是否显示当前弹窗
   */
  show: boolean;
  /**
   * 弹出层圆角
   */
  round?: boolean;
  /**
   * 是否可以点击遮罩关闭当前弹出层，同时会显示一个关闭按扭，默认否
   */
  closeable?: boolean;
  /**
   * 关闭按扭，如果设置false则不显示
   * @default 'close'
   */
  closeIcon?: string|false;
  /**
   * 关闭按扭大小
   * @default 40
   */
  closeIconSize?: number;
  /**
   * 关闭按扭位置
   */
  closeIconPosition?: PopupCloseButtonPosition,
  /**
   * 指定当前弹出层弹出位置
   */
  position?: PopupPosition,
  /**
   * 遮罩的颜色
   */
  maskColor?: string,
  /**
   * 是否显示遮罩，默认是
   * @default true
   */
  mask?: boolean,
  /**
   * 对话框偏移边距，默认为0，0，0，0
   * @default [0,0,0,0]
   */
  margin?: number[],
  /**
   * 强制设置整体边距（包括遮罩层），默认为[undefined,undefined,undefined,undefined]
   * @default [undefined,undefined,undefined,undefined]
   */
  inset?: (number|string|undefined)[],
  /**
   * 弹出层背景颜色，默认是 白色
   * @default white
   */
  backgroundColor?: string;
  /**
   * 从侧边弹出时，是否自动设置安全区，默认是
   * @default true
   */
  safeArea?: boolean,
    /**
   * 指定当前弹出层的特殊样式
   */
  innerStyle?: ViewStyle,
  /**
   * 指定弹出层动画时长，毫秒
   * @default 230
   */
  duration?: number,
  /**
   * 指定弹出层从侧边弹出的高度，如果是横向弹出，则设置宽度，默认是30%, 设置 auto 让大小自动根据内容调整
   * @default '30%'
   */
  size?: string|number;
}

const emit = defineEmits([ 'update:show', 'close', 'closeAnimFinished' ])
const props = withDefaults(defineProps<PopupProps>(), {
  closeIcon: 'close',
  closeIconSize: 40,
  closeIconPosition: 'right',
  position: 'center',
  maskColor: 'background.mask',
  mask: true,
  margin: () => [0,0,0,0],
  inset: () => {
    const arr : (number|undefined|string)[] = [undefined,undefined,undefined,undefined]
    // #ifdef H5
    arr[0] = '44px';
    // #endif
    return arr;
  },
  backgroundColor: 'white',
  safeArea: true,
  duration: 230,
  size: '30%',
});

function handleClick(e: Event) {
  e.stopPropagation();
}
function handleClose(e: Event) {
  e.stopPropagation();
  if (props.closeable)
    doClose();
}
function doClose() {
  emit('update:show', false);
  emit('close');
}

const themeContext = useTheme();

const show2 = ref(false);
const showAnimState = ref(false);
const radius = computed(() => props.round ? themeContext.resolveThemeSize('PopupRadius', 30) : 0);
const dialogSize = computed(() => themeContext.resolveThemeSize(props.size));

let lateStopTimer : SimpleDelay|undefined;

watch(() => props.show, (v) => {
  show2.value = true;
  if (!v) {
    showAnimState.value = false;
    if (lateStopTimer)
      lateStopTimer.stop();
    lateStopTimer = new SimpleDelay(undefined, () => {
      lateStopTimer = undefined;
      show2.value = false;
    }, props.duration)
    lateStopTimer.start();
  } else {
    if (lateStopTimer)
      lateStopTimer.stop();
    lateStopTimer = new SimpleDelay(undefined, () => {
      lateStopTimer = undefined;
      showAnimState.value = true
    }, 20)
    lateStopTimer.start();
  }
});
</script>

<style lang="scss">
.nana-popup {
  position: fixed;
  top: 0;
  left: 0;
  right: 0; 
  bottom: 0;
  z-index: 110;
  display: flex;
  flex-direction: column;
  pointer-events: none;
  overflow: hidden;

  &.show2 {
    pointer-events: auto;
    .nana-popup-mask {
      pointer-events: auto;
    }
  }
  &.no-mask {
    .nana-popup-mask {
      pointer-events: none;
    }
  }
  // &.stop {

  // }

  .nana-popup-mask {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 111;
    pointer-events: none;
    opacity: 0;
    transition: opacity ease-in-out 0.3s;
  }
  .nana-popup-content {
    position: relative;
    z-index: 112;
    overflow: hidden;
    transition: all ease-in-out 0.3s;
    opacity: 0.3;
    pointer-events: auto;

    &.center {
      transform: translateY(-10px);
    }
    &.top {
      transform: translateY(-100vh);
    }
    &.bottom {
      transform: translateY(200vh);
    }
    &.left {
      transform: translateX(-750rpx);
    }
    &.right {
      transform: translateX(750rpx);
    }
  }

  &.show {
    .nana-popup-mask {
      opacity: 1;
    }
    .nana-popup-content {
      opacity: 1;
      transform: translateX(0) translateY(0);
    }
  }
}

</style>