<template>
  <view 
    class="nana-bubble-box"
    :style="outerStyle"
    @mouseenter="handleHover(true)"
    @mouseleave="handleHover(false)"
  >
    <view v-if="trigger === 'click'" @click.native.capture="handleClick">
      <slot />
    </view>
    <slot v-else />
    <SimpleTransition name="bubble-box" :show="showState" :duration="200">
      <template #show="{ classNames }">
        <view class="nana-bubble-box-popup-mask" @click="hide" />
        <FlexView
          v-if="items?.length"
          position="absolute"
          :direction="direction"
          :backgroundColor="backgroundColor"
          :radius="radius"
          :gap="10"
          :padding="10"
          :zIndex="1001"
          :margin="selectObjectByType(position, 'left', {
            top: [arrowWidth,0],
            bottom: [arrowWidth,0],
            left: [0,arrowWidth],
            right: [0,arrowWidth],
          })"
          :innerClass="['nana-bubble-box-popup',position,classNames]"
          shadow="light"
          v-bind="innerProps"
          :innerStyle="innerStyle"
        >
          <view 
            class="nana-bubble-box-arrow" 
            :style="{ 
              borderWidth: theme.resolveThemeSize(arrowWidth),
              borderColor: backgroundColor,
              borderRightColor: 'transparent',
              borderBottomColor: 'transparent',
              borderLeftColor: 'transparent',
            }"
          />
          <Touchable
            v-for="item in items"
            :key="item.text"
            direction="row"
            align-items="center"
            :gap="10"
            :padding="[5, 20]"
            v-bind="itemProps"
            @click="handleItemClick(item)"
          >
            <Icon
              :name="item.icon"
              :size="44"
              :color="item.textColor || itemTextColor"
              v-bind="{ ...itemIconProps, ...item.iconProps }"
            />
            <Text 
              :wrap="false" 
              v-bind="itemTextProps" 
              :color="item.textColor || itemTextColor"
              :text="item.text" 
            />
          </Touchable>
        </FlexView>
      </template>
    </SimpleTransition>
  </view>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import { propGetThemeVar, useTheme } from '../theme/ThemeDefine';
import { selectObjectByType } from '../theme/ThemeTools';
import type { FlexProps } from '../layout/FlexView.vue';
import type { TextProps } from '../basic/Text.vue';
import Icon, { type IconProps } from '../basic/Icon.vue';
import FlexView from '../layout/FlexView.vue';
import Text from '../basic/Text.vue';
import Touchable from './Touchable.vue';
import SimpleTransition from '../anim/SimpleTransition.vue';

export interface BubbleBoxItem {
  text: string,
  textColor?: string,
  icon?: string,
  iconProps?: IconProps,
  onClick: () => void,
}
export interface BubbleBoxProps {
  /**
   * 气泡框位置
   * @default top
   */
  position?: 'left' | 'right' | 'top' | 'bottom',
  /**
   * 触发点击事件模式
   * @default click
   */
  trigger?: 'click'|'hover'|'none',
  /**
   * 气泡框按钮排列方向
   * @default column
   */
  direction?: 'column' | 'row',
  /**
   * 是否禁用
   * @default false
   */
  disabled?: boolean,
  /**
   * 气泡框按钮数组
   */
  items?: BubbleBoxItem[],
  /**
   * 气泡框按钮文本颜色
   * @default 'text.content'
   */
  itemTextColor?: string,
  /**
   * 气泡框按钮文本样式
   */
  itemTextProps?: TextProps,
  /**
   * 气泡框按钮图标样式
   */
  itemIconProps?: IconProps,
  /**
   * 气泡框按钮样式
   */
  itemProps?: FlexProps,
  /**
   * 气泡框外层容器样式
   */
  outerStyle?: Record<string, string>,
  /**
   * 气泡框背景颜色
   * @default white
   */
  backgroundColor?: string,
  /**
   * 气泡框箭头宽度
   * @default 12
   */
  arrowWidth?: number,
  /**
   * 气泡框圆角半径
   * @default 12
   */
  radius?: number,
  /**
   * 气泡框内层容器样式
   */
  innerProps?: FlexProps,
  /**
   * 气泡框内层容器样式
   */
  innerStyle?: Record<string, string>,
}
export interface BubbleBoxExpose {
  show: () => void,
  hide: () => void,
}
const theme = useTheme();
const props = withDefaults(defineProps<BubbleBoxProps>(), {
  position: 'top',
  trigger: 'click',
  direction: 'column',
  arrowWidth: () => propGetThemeVar('BubbleBoxArrowWidth', 12),
  items: () => [],
  itemTextColor: () => propGetThemeVar('BubbleBoxItemTextColor', 'text.content'),
  backgroundColor: () => propGetThemeVar('BubbleBoxBackgroundColor', 'white'),
  radius: () => propGetThemeVar('BubbleBoxRadius', 12),
});

const backgroundColor = computed(() => theme.resolveThemeColor(props.backgroundColor));
const showState = ref(false);
const lock = ref(false);

function handleItemClick(item: BubbleBoxItem) {
  hide();
  item.onClick();
}
function handleClick() {
  if (lock.value) return;
  if (props.trigger === 'click' && !props.disabled)  {
     enterLock();
    showState.value = !showState.value;
  }
}
function handleHover(show: boolean) {
  if (lock.value) return;
  if (props.trigger === 'hover' && !props.disabled)
    showState.value = show;
}

function enterLock() {
  lock.value = true;
  setTimeout(() => {
    lock.value = false;
  }, 300);
}
function show() { 
  showState.value = true;
  enterLock();
}
function hide() { 
  showState.value = false; 
  enterLock();
}

defineExpose<BubbleBoxExpose>({
  show,
  hide,
})

defineOptions({
  options: {
    virtualHost: true,
    styleIsolation: "shared",
  }
})
</script>

<style lang="scss">
.nana-bubble-box {
  position: relative;
  overflow: visible;

  .nana-bubble-box-popup {
    position: absolute;
    transition: opacity ease-in-out 0.2s;

    &.left {
      top: 50%;
      right: 100%;
      transform: translateY(-50%) translateX(0);

      .nana-bubble-box-arrow {
        top: 50%;
        left: 100%;
        transform: translateY(-50%) rotate(-90deg);
      }
    }
    &.right {
      top: 50%;
      left: 100%;
      transform: translateY(-50%);

      .nana-bubble-box-arrow {
        top: 50%;
        left: 0;
        transform: translateX(-100%) translateY(-50%) rotate(90deg);
      }
    }
    &.top {
      bottom: -100%;
      left: 50%;
      transform: translateX(-50%) translateY(-100%);

      .nana-bubble-box-arrow {
        top: 100%;
        left: 50%;
        transform: translateX(-50%) rotate(0);
      }
    }
    &.bottom {
      top: 100%;
      left: 50%;
      transform: translateX(-50%);

      .nana-bubble-box-arrow {
        top: 0;
        left: 50%;
        transform: translateX(-50%) translateY(-100%) rotate(180deg);
      }
    }
 
    &.bubble-box-enter-active,
    &.bubble-box-leave-active {
      opacity: 1;
    }
    &.bubble-box-enter-from,
    &.bubble-box-leave-to {
      opacity: 0;
    }
  }
  .nana-bubble-box-popup-mask {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1000;
  }
  .nana-bubble-box-arrow {
    position: absolute;
    width: 0;
    height: 0;
    border-style: solid;
  }
}
</style>
