<template>
  <view :style="themeStyles.container.value">
    <!-- 标题  -->
    <FlexRow v-if="title" :padding="[ 8, 0 ]" justify="space-between" align="center">
      <FlexRow :width="150" />
      <Text :innerStyle="themeStyles.title.value" :text="title" />
      <FlexRow :width="150">
        <Button
          v-if="showCloseButton"
          type="text"
          textColor="primary"
          :pressedColor="keyPressedColor" 
          :text="finishButtonText"
          @click="emit('finish')"
        />
      </FlexRow>
    </FlexRow>
    <FlexRow v-else-if="showCloseButton" justify="center" :padding="[ 3, 6 ]">
      <Button 
        type="text"
        :innerStyle="{ width: '100%' }"
        :pressedColor="keyPressedColor"
        icon="arrow-down"
        @click="emit('finish')" 
      />
    </FlexRow>
    <slot name="top" />
    <!-- 键盘区域 -->
    <view :style="themeStyles.keyPadOut.value">
      <view :style="{
        ...themeStyles.keyPadKeys.value,
        paddingBottom: themeContext.resolveSize(keyMargin),
        paddingRight: themeContext.resolveSize(keyMargin),
      }">
        <!-- 主区域 -->
        <NumberKeyBoardKey 
          v-for="(key, i) in mainKeys"
          :key="i"
          :text="key[0]"
          :icon="key[1]"
          :action="key[2]"
          :widthCount="key[3]"
          :heightCount="key[4]"
          :side="key[5]"
          @click="onKeyClick"
        />
      </view>

      <view v-if="showSideButtons" :style="{
        ...themeStyles.keyPadSide.value,
        paddingBottom: themeContext.resolveSize(keyMargin),
      }">
        <!-- 侧边区域 -->
        <template 
          v-for="(key, i) in sideKeys"
          :key="i"
        >
          <!-- 完成键 -->
          <NumberKeyBoardKey 
            v-if="key.key === 'finish'"
            :text="finishButtonText"
            :icon="false"
            :action="'finish'"
            :widthCount="1"
            :heightCount="key.span"
            :side="true"
            @click="onKeyClick"
          />
          <!-- 后退键 -->
          <NumberKeyBoardKey 
            v-else-if="key.key === 'delete'"
            :text="'delete'"
            :icon="true"
            :action="'delete'"
            :widthCount="1"
            :heightCount="key.span"
            :side="true"
            @click="onKeyClick"
          />
          <!-- 其他键 -->
          <NumberKeyBoardKey 
            v-else
            :text="key.key"
            :icon="key.icon === true"
            :action="'extra'"
            :widthCount="1"
            :heightCount="key.span"
            :side="true"
            @click="onKeyClick"
          />
        </template>
      </view> 
    </view>
    <Height :size="30" />
  </view>
</template>

<script setup lang="ts">
import { computed, provide, toRef, type Ref } from 'vue';
import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { DynamicColor, DynamicSize, DynamicVar } from '../theme/ThemeTools';
import FlexRow from '../layout/FlexRow.vue';
import Text from '../basic/Text.vue';
import Button from '../basic/Button.vue';
import Height from '../layout/space/Height.vue';
import NumberKeyBoardKey from './NumberKeyBoardKey.vue';
import { NumberKeyBoardKeys, NumberKeyBoardSideKeys, type NumberKeyBoardExtraKey, type NumberKeyBoardSideKey } from './NumberKeyBoardDefine';
import Feedback from '../utils/Feedback';

export interface NumberKeyBoardInnerProps {
  /**
   * 键盘标题
   */
  title?: string;
  /**
   * 键盘宽度
   * @default 750
   */
  width?: number;
  /**
   * 默认数字按键数组。
   * @default `[ '1', '2', '3', '4', '5', '6', '7', '8', '9', 'close', '0', 'delete' ]`
   */
  defaultKeys?: string[],
  /**
   * 默认数字按键数组。
   * @default `[ '1', '2', '3', '4', '5', '6', '7', '8', '9', 'close', '0', 'delete' ]`
   */
  sideKeys?: NumberKeyBoardSideKey[],
  /**
   * 键盘额外按键。 showSideButtons 为 true 时可配置2个额外按键，false 时可配置1个额外按键。
   */
  extraKeys?: NumberKeyBoardExtraKey[];
  /**
   * 是否显示侧栏，当显示侧栏时，完成与删除按钮显示在侧栏，您可以使用 extraKey 配置额外的2个按键。
   * @default false
   */
  showSideButtons?: boolean;
  /**
   * 是否显示关闭按钮。当显示 title 时，这个属性也用来控制标题栏上面的完成按钮是否显示。
   * @default true
   */
  showCloseButton?: boolean;
  /**
   * 完成按钮文字
   * @default '完成'
   */
  finishButtonText?: string;
  /**
   * 按键高度
   * @default 100
   */
  keyHeight?: number;
  /**
   * 键盘之间的间距
   * @default 8
   */
  keyMargin?: number,
  /**
   * 键盘显示按键列数（不包括侧栏）。
   * @default 3
   */
  keyColNum?: number,
  /**
   * 自定义按键的样式
   */
  keyStyle?: ViewStyle;
  /**
   * 自定义按键文字的样式
   */
  keyTextStyle?: TextStyle;
  /**
   * 按键的背景颜色。
   * @default white
   */
  keyColor?: string;
  /**
   * 完成按键的文字颜色。
   * @default black
   */
  keyTextColor?: string;
  /**
   * 完成按键的背景颜色。
   * @default primary
   */
  keyFinishColor?: string;
  /**
   * 完成按键的文字颜色。
   * @default white
   */
  keyFinishTextColor?: string;
  /**
   * 完成按键的按下时的颜色
   * @default pressed.white
   */
  keyFinishPressedColor?: string;
  /**
   * 自定义按键按下时的颜色
   * @default pressed.white
   */
  keyPressedColor?: string;
  /**
   * 按键按下时是否有触感反馈
   * @platform iOS
   * @default true
   */
  keyPressedImpactFeedback?: boolean;
  /**
   * 是否随机排序数字键盘，常用于安全等级较高的场景。
   * @default false
   */
  keyRandomOrder?: boolean;
}

const props = withDefaults(defineProps<NumberKeyBoardInnerProps>(), {
  width: 750,
  showSideButtons: false,
  keyPressedImpactFeedback: true,
  keyRandomOrder: false,
  showCloseButton: true,
  keyFinishColor: () => propGetThemeVar('NumberKeyBoardKeyFinishColor', 'primary'),
  keyFinishPressedColor: () => propGetThemeVar('NumberKeyBoardKeyFinishPressedColor', 'pressed.white'),
  keyColor: () => propGetThemeVar('NumberKeyBoardKeyColor', 'white'),
  keyPressedColor: () => propGetThemeVar('NumberKeyBoardKeyPressedColor', 'pressed.white'),
  keyFinishTextColor: () => propGetThemeVar('NumberKeyBoardKeyFinishTextColor', 'white'),
  keyTextColor: () => propGetThemeVar('NumberKeyBoardKeyTextColor', 'black'),
  finishButtonText: () => propGetThemeVar('NumberKeyBoardKeyFinishButtonText', '完成'),
  keyHeight: 100,
  keyMargin: 8,
  keyColNum: 3,
  defaultKeys: () => NumberKeyBoardKeys,
  sideKeys: () => NumberKeyBoardSideKeys,
  extraKeys: () => [],
});
const emit = defineEmits([ 'finish', 'input', 'delete' ])

const themeContext = useTheme();
const themeStyles = themeContext.useThemeStyles({
  container: {
    position: 'relative',
    display: 'flex',
    flexDirection: 'column',
    backgroundColor: DynamicColor('NumberKeyBoardBackgroundColor', 'background.page'),
  },
  keyPadOut: {
    position: 'relative',
    flexDirection: 'row',
    display: 'flex',
  },
  keyPadKeys: {
    display: 'flex',
    flexDirection: 'row',
    flex: DynamicVar('NumberKeyBoardPadKeysFlex', 3),
    flexWrap: 'wrap',
    justifyContent: 'center',
  },
  keyPadSide: {
    display: 'flex',
    position: 'relative',
    flexDirection: 'row',
    flexWrap: 'wrap',
    flex: DynamicVar('NumberKeyBoardPadSideFlex', 1),
    justifyContent: 'flex-start',
  },
  key: {
    display: 'flex',
    height: DynamicSize('NumberKeyBoardKeyHeight', 20),
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: DynamicSize('NumberKeyBoardKeyBorderRadius', 12),
  },
  title: {
    color: DynamicColor('NumberKeyBoardTitleColor', 'black'),
    fontSize: DynamicSize('NumberKeyBoardTitleFontSize', 32),
  },
  keyText: {
    fontSize: DynamicSize('NumberKeyBoardKeyFontSize', 46),
  },
});
const keyTextStyle = computed(() => ({
  ...themeStyles.keyText.value,
  ...props.keyTextStyle,
  color: themeContext.resolveThemeColor(props.keyTextColor),
}));
const keyTextStyleFinish = computed(() => ({
  ...themeStyles.keyText.value,
  fontSize: themeContext.resolveThemeSize('NumberKeyBoardKeyFinishFontSize', 40),
  ...props.keyTextStyle,
  color: themeContext.resolveThemeColor(props.keyFinishTextColor),
}));

//计算按键占用宽度
const keyColNumFinal = computed(() => props.keyColNum + (props.showSideButtons ? 1 : 0));
const keyWidthBase = computed(() => (props.width - props.keyMargin * (keyColNumFinal.value + 1)) / keyColNumFinal.value);

//传递到子组件使用
export type NumberKeyBoardContext = {
  keyTextStyle: Ref<TextStyle>,
  keyTextStyleFinish: Ref<TextStyle>,
  keyWidthBase: Ref<number>,
  keyColNumFinal: Ref<number>,
  keyMargin: Ref<number>,
  keyColor: Ref<string>,
  keyFinishColor: Ref<string>,
  keyFinishPressedColor: Ref<string>,
  keyPressedColor: Ref<string>,
  keyStyle: Ref<ViewStyle|undefined>,
  keyHeight: Ref<number>,
}
provide<NumberKeyBoardContext>('NumberKeyBoardContext', {
  keyTextStyle,
  keyTextStyleFinish,
  keyWidthBase,
  keyColNumFinal,
  keyMargin: toRef(props.keyMargin),
  keyColor: toRef(props.keyColor),
  keyFinishColor: toRef(props.keyFinishColor),
  keyFinishPressedColor: toRef(props.keyFinishPressedColor),
  keyPressedColor: toRef(props.keyPressedColor),
  keyHeight: toRef(props.keyHeight),
  keyStyle: toRef(props.keyStyle),
});

//按键点击事件
function onKeyClick(action: string, text: string) {
  if (props.keyPressedImpactFeedback)
    Feedback.impactSelectionFeedbackGenerator();
  if (action === 'delete')
    emit('delete');
  else if (action === 'finish')
    emit('finish');
  else
    emit('input', text);
}
//生成随机数字顺序
function makeRandomKeys() {
  const noNumberKeys = props.defaultKeys.filter((k) => k.length !== 1);
  const numberKeys = props.defaultKeys.filter((k) => k.length === 1).sort(() => 0.5 - Math.random());
  return numberKeys.concat(noNumberKeys);
}

type MainKeyData = [string, boolean, string, number, number, boolean];

//主按键生成
const mainKeys = computed(() => {

  const arr = [] as MainKeyData[];
  const keys = props.keyRandomOrder ? makeRandomKeys() : props.defaultKeys;

  //循环按键
  for (let i = 0; i < keys.length; i++) {
    if (keys[i] === 'delete') {
      if (props.showSideButtons)
        //删除在显示侧栏时按钮无需添加，因为侧栏已经有一个了
        arr.push(['', false, '', 1, 1, false]);
      else
        arr.push(['delete', true, 'delete', 1, 1, false]);
      continue;
    }

    //添加Key
    arr.push([keys[i], keys[i].length > 1, 'key' + i, 1, 1, false]);
  }

  //添加更多的按键
  if (props.extraKeys.length > 0) {
    props.extraKeys.forEach((key, i) => {
      const keyEle = [ key.key, key.icon === true, 'extra' + i, key.span || 1, key.height || 1, false ] as MainKeyData;
      if (key.order) {//插入或者替换
        if (key.replace)
          arr[key.order] = keyEle;
        else
          arr.splice(key.order, 0, keyEle);
      }
      else
        arr.push(keyEle);
    });
  }

  return arr;
});

</script>