<template>
  <view
    :id="innerId"
    :class="[
      'nana-flex-layout', { 
        'nana-flex-row': direction === 'row', 
        'nana-flex-column': direction === 'column' 
      },
      innerClass,
    ]"
    :style="finalStyle"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
    @mousedown="handleTouchStart"
    @mouseup="handleTouchEnd"
    @touchstart="handleTouchStart"
    @touchend="handleTouchEnd"
    @click="handleClick"
  >
    <slot></slot>
  </view>
</template>

<script setup lang="ts">

/**
 * 组件说明：Flex组件，用于一些布局中快速写容器，是一系列盒子的基础组件。
 */
import { computed, onMounted, ref } from 'vue';
import { useTheme, type ThemePaddingMargin } from '../theme/ThemeDefine';
import { configMargin, configPadding } from '../theme/ThemeTools';

export type FlexDirection = "row"|"column"|'row-reverse'|'column-reverse';
export type FlexJustifyType =  'flex-start' | 'flex-end' | 'center' |'space-between' |'space-around' |'space-evenly';
export type FlexAlignType = "stretch"|'center'|'start'|'end'|'flex-start' | 'flex-end' | 'center';
export type StateType = 'default' | 'active' | 'pressed';

export interface FlexProps {
  innerId?: string,
  /**
   * 盒子定位
   */ 
  position?: "absolute" | "relative",
  /**
   * 弹性盒子方向
   */
  direction?: FlexDirection,
  /**
   * 子元素在主轴上的对齐方式
   */
  justify?: FlexJustifyType,
  /**
   * 子元素在交叉轴上的对齐方式
   */
  align?: FlexAlignType|"auto",
  /**
   * 当前元素在主轴上的对齐方式
   */
  alignSelf?: FlexAlignType|"auto",
  /**
   *  主轴与交叉轴是否居中
   */
  center?: boolean,
  /**
   * 弹性布局是否换行
   */
  wrap?: boolean,
  /**
   * 特殊样式
   */
  innerStyle?: object,
  /**
   * 特殊类名
   */
  innerClass?: string|string[]|object,
  /**
   * flex 参数
   */
  flex?: number|string,
  /**
   * flexBasis 参数
   */
  flexBasis?: number|string,
  /**
   * flexGrow 参数
   */
  flexGrow?: number,
  /**
   * flexShrink 参数
   */
  flexShrink?: number,
  /**
   * 内边距参数（支持数字或数组）
   */
  padding?: number|Array<number>|ThemePaddingMargin,
  /**
   * 外边距参数（支持数字或数组）
   */
  margin?: number|Array<number>|ThemePaddingMargin,
  /**
   * 位置参数
   */
  top?: number|string,
  right?: number|string,
  bottom?: number|string,
  left?: number|string,
  /**
   * 圆角
   */
  radius?: number|string,
  /**
   * 间距
   */
  gap?: number|string,
  /**
   * 是否可以点击
   */
  touchable?: boolean,
  /**
   * 背景颜色
   */
  backgroundColor?: string,
  /**
   * 按下时的颜色
   */
  pressedColor?: string,
  /**
   * 按下时的透明度（仅在 pressedColor 未设置时有效）
   */
  activeOpacity?: number,
  /**
   * 宽度
   */
  width?: number|string,
  /**
   * 高度
   */
  height?: number|string,

  overflow?: 'visible'|'hidden'|'scroll'|'auto'
}

const props = withDefaults(defineProps<FlexProps>(), {
  direction: "column",
  backgroundColor: '',
  activeOpacity: 0.7,
  touchable: false,
});

const themeContext = useTheme();

const commonStyle = computed(() => {
  const obj : Record<string, any> = {
    flexDirection: props.direction,
    flexBasis: props.flexBasis,
    flexGrow: props.flexGrow,
    flexShrink: props.flexShrink,
    justifyContent: props.center ? (props.justify || 'center') : props.justify,
    alignItems: props.center ? (props.align || 'center') : props.align,
    position: props.position,
    alignSelf: props.alignSelf,
    flexWrap: props.wrap ? 'wrap' : 'nowrap',
    backgroundColor: themeContext.resolveThemeColor(props.backgroundColor),
    width: themeContext.resolveThemeSize(props.width),
    height: themeContext.resolveThemeSize(props.height),
    gap: themeContext.resolveThemeSize(props.gap),
    borderRadius: themeContext.resolveThemeSize(props.radius),
    overflow: props.overflow,
    ...(props.innerStyle ? props.innerStyle : {}),
  }
  
  //内边距样式
  configPadding(obj, themeContext.theme, props.padding as any);
  //外边距样式
  configMargin(obj, themeContext.theme, props.margin as any);

  if (obj.paddingVertical) {
    if (obj.paddingTop === undefined)
      obj.paddingTop = obj.paddingVertical;
    if (obj.paddingBottom === undefined)
      obj.paddingBottom = obj.paddingVertical;
    obj.paddingVertical = undefined;
  }
  if (obj.paddingHorizontal) {
    if (obj.paddingLeft === undefined)
      obj.paddingLeft = obj.paddingHorizontal;
    if (obj.paddingRight === undefined)
      obj.paddingRight = obj.paddingHorizontal;
    obj.paddingHorizontal = undefined;
  }
  if (obj.marginVertical) {
    obj.marginTop = obj.marginVertical;
    obj.marginBottom = obj.marginVertical;
    obj.marginVertical = undefined;
  }
  if (obj.marginHorizontal) {
    obj.marginLeft = obj.marginHorizontal;
    obj.marginRight = obj.marginHorizontal;
    obj.marginHorizontal = undefined;
  }

  //绝对距样式
  if (typeof props.left !== 'undefined')
    obj.left = themeContext.resolveThemeSize(props.left);
  if (typeof props.right !== 'undefined')
    obj.right = themeContext.resolveThemeSize(props.right);
  if (typeof props.top !== 'undefined')
    obj.top = themeContext.resolveThemeSize(props.top);
  if (typeof props.bottom !== 'undefined')
    obj.bottom = themeContext.resolveThemeSize(props.bottom);
  if (typeof props.flex !== 'undefined')
    obj.flex = props.flex;

  return obj
});
const finalStyle = computed(() => {
  const obj : Record<string, any> = {};
  if (props.pressedColor != undefined) { 
    if (isPressed.value)
      obj.backgroundColor = themeContext.resolveThemeColor(props.pressedColor);
  } else if (props.activeOpacity != undefined) 
    obj.opacity = isPressed.value ? props.activeOpacity : 1;
  const o = {
    ...commonStyle.value,
    ...obj
  } 
  for (const key in o) {
    if (o[key] === undefined)
      delete o[key]; 
  }
  return o;
})

defineOptions({
  options: {
    styleIsolation: "shared",
    virtualHost: true
  }
})
const emit = defineEmits([ "click", "state" ]);
const isPressed = ref(false)

function handleTouchStart() {
  if (props.touchable) {
    isPressed.value = true; // 按下时改变状态
    emit('state', 'active');
  }
}
function handleMouseEnter() {
  if (props.touchable)
    emit('state', 'active')
}
function handleMouseLeave() {
  if (props.touchable)
    emit('state', 'default')
}
function handleClick(e: Event) {
  if (props.touchable)
    emit('click', e);
}
function handleTouchEnd() {
  if (props.touchable) {
    isPressed.value = false; // 释放时恢复状态
    emit('state', 'default');
  }
}

onMounted(() => {
  emit('state', 'default')
})
</script>

<style>
.nana-flex-layout {
  display: flex;
}
.nana-flex-row {
  flex-direction: row;
}
.nana-flex-column {
  flex-direction: column;
}
</style>