<!-- 如果是 一维数组 则选中一个值,返回一个值；如果是二维数组，则返回每一列选中值组成的数组 -->
<template>
  <view class="w-picker">
    <view class="w-picker-wrapper" @click.passive="onShowPicker">
      <slot
        name="trigger"
        :label="state.keyNameValue"
        :value="state.valueNameValue"
      >
        <up-input
          readonly
          :border="border"
          v-model="state.keyNameValue"
          :inputAlign="align"
          :placeholder="placeholder"
          suffixIcon="arrow-right"
          :placeholder-style="`color: ${placeholderColor}`"
          :suffixIconStyle="{
            color: state.keyNameValue ? color : placeholderColor,
          }"
          :fontSize="size"
          :color="color"
        >
          <template #suffix v-if="state.keyNameValue">
            <view style="width: 12px" @click.stop="onClear">
              <view style="position: absolute; top: 0; bottom: 0; z-index: 100">
                <view class="clear" :style="iconStyle">
                  <u-icon name="close" size="8" color="#fff"></u-icon>
                </view>
              </view>
            </view>
          </template> </up-input
      ></slot>
      <div class="input-cover"></div>
    </view>
    <up-picker
      ref="uPickerRef"
      v-model="state.valueNameValue"
      :show="show"
      :columns="state.columns"
      :title="title"
      :closeOnClickOverlay="closeOnClickOverlay"
      keyName="_wPickerShowName"
      :defaultIndex="state.defaultIndex"
      :loading="loading"
      @close="close"
      @cancel="cancel"
      @confirm="confirm"
      @change="change"
    ></up-picker>
  </view>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watchEffect } from "vue";
type NameProps = {
  keyName: string;
  valueName: string;
};
interface Props {
  modelValue: any; // 选中值(一维数组或二维数组(只有一项时)，返回一个值；二维数组(多于1项)时，返回每一列选中值组成的数组)
  columns: any[]; // 数据源 二维数组
  keyName?: string; //显示的属性名
  valueName?: string; //存储的属性名

  align?: "left" | "center" | "right" | undefined; //对齐方式 left\center\right
  border?: "none" | "bottom" | "surround" | undefined; // surround四周有边框,bottom底部有边框,none没有边框
  shape?: "circle" | "square" | undefined; //输入框形状 circle-圆形，square-方形 （ 默认 'square' ）

  title?: string; // 弹窗顶部标题
  size?: string; //文本大小
  color?: string; //选中的颜色
  placeholder?: string; //未选择时,提示文字
  placeholderColor?: string; //占位颜色
  closeOnClickOverlay?: boolean; //是否允许点击遮罩关闭选择器  ( 默认 false )
  nameConfig?: NameProps[]; // 多维数组时，指定每一层的keyName和valueName, 例如：[{keyName:'name',valueName:'code'},{keyName:'name',valueName:'uname'}]，不传则默认使用keyName和valueName
}

const props = withDefaults(defineProps<Props>(), {
  border: "none",
  shape: "square",
  keyName: "name",
  valueName: "code",
  placeholder: "请选择",
  placeholderColor: "#c0c4cc",
  color: "#303133",
  size: "15",
});

const iconStyle = computed(() => ({
  transform: props.border === "none" ? "translateY(5px)" : "translateY(11px)",
}));

const uPickerRef = ref();
const loading = ref(false);
// 集中到这里处理
const state = reactive<any>({
  columns: [],
  valueNameValue: [], //选中后的值,
  keyNameValue: "", //选中后显示的值
  defaultIndex: [], // //默认选中索引[]
  keyName: props.keyName ?? "name",
  valueName: props.valueName ?? "id",
  innerValueName: "id", // 组件内部属性名固定为id
  nameConfig: [] as NameProps[], // 多维数组时，指定每一层的keyName和valueName, 例如：[{keyName:'name',valueName:'code'},{keyName:'name',valueName:'uname'}]，不传则默认使用keyName和valueName
});

//默认不弹出
const show = ref(false);

//事件抛出
const emit = defineEmits([
  "close",
  "cancel",
  "confirm",
  "change",
  "update:modelValue",
]);

const onShowPicker = () => {
  show.value = true;
};

//确认
const confirm = (d: any) => {
  show.value = false;
  // 判断是否有未选中的列
  let flag = d.value.some((item: any) => {
    return !item;
  });
  if (flag) {
    emit("confirm", d);
    return;
  }

  // 如果第一项为对象
  if (Object.prototype.toString.call(d.value[0]) === "[object Object]") {
    // 多维对象数组
    if (getArrayDepth(props.columns) == 2) {
      // 多维对象数组
      const _valueNames: any[] = [];
      for (let i = 0; i < d.value.length; i++) {
        _valueNames.push(d.value[i]["id"]);
      }
      state.valueNameValue = _valueNames;
    } /*一维 */ else state.valueNameValue = d.value[0][props.valueName];
  } else {
    if (getArrayDepth(props.columns) == 1) {
      state.valueNameValue = d.value[0];
    } else state.valueNameValue = d.value;
  }
  emit("update:modelValue", state.valueNameValue);
  emit("confirm", d);
};
//取消
const cancel = () => {
  show.value = false;
  emit("cancel");
};
//关闭
const close = () => {
  show.value = false;
  emit("close");
};
//改变
const change = (d: any) => {
  const { columnIndex } = d;
  // 最后一列不处理
  if (!state.nameConfig[columnIndex + 1]) {
    emit("change", d, loading, () => {});
    return;
  }
  emit("change", d, loading, setColumnValues);

  function setColumnValues(nextColumnData: any) {
    // 映射关系
    let valueName = state.nameConfig[columnIndex + 1]?.valueName; // 下一级valueName
    let keyName = state.nameConfig[columnIndex + 1]?.keyName; // 下一级valueName
    const tempNextData: any = [];
    if (
      nextColumnData &&
      Array.isArray(nextColumnData) &&
      nextColumnData.length > 0
    ) {
      // 下一级数据
      for (let i = 0; i < nextColumnData.length; i++) {
        if (valueName != "id") {
          Reflect.deleteProperty(nextColumnData[i], "id");
        }
        tempNextData[i] = {
          id: nextColumnData[i][valueName],
          _wPickerShowName: nextColumnData[i][keyName],
          ...nextColumnData[i],
        };
      }
      // 设置下一级数据
      uPickerRef.value.setColumnValues(columnIndex + 1, tempNextData);
    }
  }
};
const onClear = () => {
  state.keyNameValue = "";
  emit("update:modelValue", null);
};
const reset = () => {
  state.keyNameValue = "";
};

watchEffect(() => {
  if (props.keyName) state.keyName = props.keyName;
  if (props.valueName) state.valueName = props.valueName;
  //一维数组 : 表示单列选择
  if (getArrayDepth(props.columns) == 1) {
    // 如果是对象数组 [{code:1,name:xxx},{code:2,name:xxx}]
    if (
      Object.prototype.toString.call(props.columns[0]) === "[object Object]"
    ) {
      let _columns = JSON.parse(JSON.stringify(props.columns));
      for (let i = 0; i < props.columns.length; i++) {
        _columns[i].id = props.columns[i][props.valueName];
        _columns[i]._wPickerShowName = props.columns[i][props.keyName];
        if (props.columns[i][props.valueName] == props.modelValue) {
          state.keyNameValue = props.columns[i][props.keyName];
          state.defaultIndex = [i];
          state.valueNameValue = [props.columns[i][props.valueName]];
        }
      }
      state.columns = [_columns];
    } else {
      // 如果是一维非对象数组 ["a","b","c"]
      state.columns = [JSON.parse(JSON.stringify(props.columns))];
      for (let i = 0; i < props.columns.length; i++) {
        if (props.columns[i] == props.modelValue) {
          state.keyNameValue = props.columns[i];
          state.defaultIndex = [i];
          state.valueNameValue = [props.columns[i]];
          break;
        }
      }
    }
  }
  //二维数组 : 表示多列选择[[{code:1,name:xxx},{code:2,name:xxx}],[{code:1-2,name:xxx},{code:2-2,name:xxx}]]
  if (getArrayDepth(props.columns) == 2) {
    const _valueNames: any[] = [];
    const _keyNames: any[] = [];
    const _defaultIndex: number[] = [];
    if (
      Object.prototype.toString.call(props.columns[0][0]) === "[object Object]"
    ) {
      state.columns = JSON.parse(JSON.stringify(props.columns));
      let len = props.columns.length;
      // 统一设置nameConfig的keyName和valueName
      if (props.nameConfig && Array.isArray(props.nameConfig)) {
        for (let i = 0; i < len; i++) {
          state.nameConfig[i] = {};
          if (props.nameConfig[i].keyName) {
            state.nameConfig[i].keyName = props.nameConfig[i].keyName;
          } else {
            state.nameConfig[i].keyName = props.keyName ?? "name";
          }
          if (props.nameConfig[i].valueName) {
            state.nameConfig[i].valueName = props.nameConfig[i].valueName;
          } else {
            state.nameConfig[i].valueName = props.valueName ?? "code";
          }
        }
      } else {
        // 如果nameConfig没有设置，则默认设置每一列都props.keyName和props.valueName, 若keyName和valueName没设，则默认为name和code
        for (let i = 0; i < len; i++) {
          state.nameConfig[i] = {
            keyName: props.keyName ?? "name",
            valueName: props.valueName ?? "code",
          };
        }
      }
      // 将state.columns中的每一层都设为nameConfig中固定的keyName和valueName
      for (let i = 0; i < len; i++) {
        for (let j = 0; j < props.columns[i].length; j++) {
          state.columns[i][j] = {
            [state.valueName]:
              props.columns[i][j][state.nameConfig[i].valueName],
            id: props.columns[i][j][state.nameConfig[i].valueName],
            [state.keyName]: props.columns[i][j][state.nameConfig[i].keyName],
            _wPickerShowName: props.columns[i][j][state.nameConfig[i].keyName],
          };
        }
      }
      // 根据props.modelValue  组装columns的默认显示值及index列表
      if (Array.isArray(props.modelValue) && props.modelValue?.length) {
        for (let i = 0; i < props.modelValue.length; i++) {
          for (let j = 0; j < state.columns[i].length; j++) {
            if (state.columns[i][j]["id"] == props.modelValue[i]) {
              _valueNames[i] = state.columns[i][j][state.valueName];
              _keyNames[i] = state.columns[i][j][state.keyName];
              _defaultIndex[i] = j;
              break;
            }
          }
        }
      }
    } else {
      // 非对象数组
      state.columns = [...props.columns];
      // 根据props.modelValue  组装columns的默认显示值及index列表
      if (Array.isArray(props.modelValue) && props.modelValue?.length) {
        for (let i = 0; i < props.modelValue.length; i++) {
          for (let j = 0; j < props.columns[i].length; j++) {
            if (props.columns[i][j] == props.modelValue[i]) {
              _valueNames[i] = props.columns[i][j];
              _keyNames[i] = props.columns[i][j];
              _defaultIndex[i] = j;
              break;
            }
          }
        }
      }
    }
    state.defaultIndex = [..._defaultIndex];
    state.valueNameValue = [..._valueNames];
    state.keyNameValue = [..._keyNames].join("/");
  }
});

// 判断是几维数组
function getArrayDepth(arr: any) {
  if (!Array.isArray(arr)) return 0; // 如果不是数组，返回深度 0
  let maxDepth = 1; // 默认深度为 1
  for (let item of arr) {
    if (Array.isArray(item)) {
      const depth = getArrayDepth(item) + 1; // 递归计算深度
      if (depth > maxDepth) {
        maxDepth = depth;
      }
    }
  }
  return maxDepth;
}

defineExpose({ reset });
</script>
<style scoped lang="scss">
@mixin flex($direction: row) {
  display: flex;
  flex-direction: $direction;
}

.w-picker {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  .w-picker-wrapper {
    position: relative;
    width: 100%;
    cursor: pointer;
  }
  .clear {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #c1c1c1;
    width: 15px;
    height: 15px;
    line-height: 15px;
    border-radius: 50%;
    .u-icon {
      margin-top: 1px;
    }
  }
}
.u-input {
  @include flex(row);
  align-items: center;
  flex: 1;

  &--radius,
  &--square {
    border-radius: 4px;
  }

  &--no-radius {
    border-radius: 0;
  }

  &--circle {
    border-radius: 100px;
  }
}
.input-cover {
  opacity: 0;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1;
}
</style>
