<template>
  <Popup
    :show="popupShow"
    @close="onCancel"
    :closeIcon="false"
    position="bottom"
    closeable
  >
    <PopupTitle 
      relative
      :title="title"
      :closeable="true"
      @close="onCancel"
    />
    <Cascader 
      v-bind="props"
      :modelValue="tempValue"
      @update:modelValue="(v:any) => tempValue = v"
      @selectTextChange="onSelectTextChange"
      @pickEnd="onPickEnd"
    />
    <slot name="footer">
      <Height :size="20" />
    </slot>
  </Popup>
  <Text 
    v-if="showSelectText"
    :size="30"
    :color="selectText && !(readonly || disabled) ? 'text.content' : 'text.second'"
    :text="selectText || placeholder" 
    :maxWidth="300"
    textAlign="left"
    v-bind="textProps"
  />
</template>

<script setup lang="ts">
import { ref, toRef, watch } from 'vue';
import { useFieldChildValueInjector } from './FormContext';
import { usePickerFieldTempStorageData } from './PickerUtils';
import type { CascaderProps } from './Cascader.vue';
import Popup from '../dialog/Popup.vue';
import Cascader from './Cascader.vue';
import Height from '../layout/space/Height.vue';
import Text, { type TextProps } from '../basic/Text.vue';
import PopupTitle from '../dialog/PopupTitle.vue';
import { getCascaderText } from './CascaderUtils';
import { usePickerFieldInstance } from './Picker';

export interface CascaderFieldProps extends Omit<CascaderProps, 'modelValue'> {
  /**
   * 是否禁用
   */
  disabled?: boolean,
  /**
   * 是否只读
   */
  readonly?: boolean,
  
  modelValue?: (string|number)[];
  /**
   * 标题
   */
  title?: string,
  /**
   * 是否显示选择的文本。
   * @default true
   */
  showSelectText?: boolean,
  /**
   * 占位符
   */
  placeholder?: string,
  /**
   * 初始值
   */
  initalValue?: string[],
  /**
   * 是否在选择完成后立即更新值。
   * @default false
   */
  shouldUpdateValueImmediately?: boolean,
  /**
   * 显示的文本属性
   */
  textProps?: TextProps,
  /**
   * 确认前的回调
   * @param value 选中的值
   * @returns 返回true可以阻止关闭弹窗
   */
  beforeConfirm?: (value: (string|number)[]|undefined) => Promise<boolean>,
}

const emit = defineEmits([ 'update:modelValue', 'cancel', 'confirm', 'selectTextChange', 'tempValueChange' ]);
const props = withDefaults(defineProps<CascaderFieldProps>(), {
  modelValue: () => [],
  title: '请选择',
  placeholder: '请选择',
  titleProps: () => ({
    cancelText: '取消',
    confirmText: '确定',
  }),
  showSelectText: true,
  autoConfirm: true,
  textKey: 'text',
  valueKey: 'value',
  childrenKey: 'children',
});

const popupShow = ref(false);

const {
  value,
  updateValue,
} = useFieldChildValueInjector(
  toRef(props, 'modelValue'), 
  (v) => emit('update:modelValue', v),
  undefined,
  () => {
    popupShow.value = true;
  },
  props.initalValue,
);

const {
  onSelectTextChange,
  onCancel,
  onConfirm,
  selectText,
  tempValue,
} = usePickerFieldTempStorageData(
  value,
  updateValue,
  () => popupShow.value = false,
  emit as any,
  [],
  props.shouldUpdateValueImmediately,
  props.beforeConfirm,
  popupShow,
);

function onPickEnd() {
  if (props.autoConfirm)
    onConfirm();
}

watch(tempValue, (v) => {
  if (!popupShow.value)
    onSelectTextChange(getCascaderText(
      v, 
      props.valueKey, 
      props.textKey, 
      props.childrenKey, 
      props.data
    ), true);
}, { immediate: true })

defineExpose({
  confirm: onConfirm,
  cancel: onCancel,
  ...usePickerFieldInstance(popupShow),
})
defineOptions({
  options: {
    styleIsolation: "shared",
    virtualHost: true,
  }
})
</script>