import { deepClone } from "@/utils/index";
import {
  ElRow,
  ElRate,
  ElInput,
  ElSlider,
  ElSelect,
  ElButton,
  ElSwitch,
  ElUpload,
  ElCascader,
  ElDatePicker,
  ElTimePicker,
  ElRadioGroup,
  ElColorPicker,
  ElInputNumber,
  ElCheckboxGroup,
} from "element-plus";
import Editor from "@/components/Editor";
import { h, defineComponent } from "vue";

const formComponentsMap = {
  "el-row": ElRow,
  "el-rate": ElRate,
  "el-input": ElInput,
  "el-switch": ElSwitch,
  "el-select": ElSelect,
  "el-upload": ElUpload,
  "el-button": ElButton,
  "el-slider": ElSlider,
  "el-cascader": ElCascader,
  "el-time-picker": ElTimePicker,
  "el-radio-group": ElRadioGroup,
  "el-date-picker": ElDatePicker,
  "el-input-number": ElInputNumber,
  "el-color-picker": ElColorPicker,
  "el-checkbox-group": ElCheckboxGroup,
  editor: Editor,
};

const componentChild = {};
/**
 * 将./slots中的文件挂载到对象componentChild上
 * 文件名为key，对应JSON配置中的__config__.tag
 * 文件内容为value，解析JSON配置中的__slot__
 */
const slotsFiles = import.meta.glob("./slots/*.jsx", { eager: true });
// const slotsFiles = require.context("./slots", false, /\.js$/);
const keys = Object.keys(slotsFiles) || [];
keys.forEach((key) => {
  const tag = key.replace(/^\.\/slots\/(.*)\.\w+$/, "$1");
  componentChild[tag] = slotsFiles[key].default;
});

function vModel(dataObject, defaultValue) {
  dataObject.props.value = defaultValue;
  dataObject.on.input = (val) => {
    this.$emit("input", val);
  };
  dataObject.on.change = (val) => {
    this.$emit("input", val);
  };
}

function mountSlotFiles(confClone, children) {
  const childObjs = componentChild[confClone.__config__.tag];
  if (childObjs) {
    Object.keys(childObjs).forEach((key) => {
      const childFunc = childObjs[key];
      if (confClone.__slot__ && confClone.__slot__[key]) {
        children.push(childFunc(confClone, key));
      }
    });
  }
}

function emitEvents(confClone) {
  ["on", "nativeOn"].forEach((attr) => {
    const eventKeyList = Object.keys(confClone[attr] || {});
    eventKeyList.forEach((key) => {
      const val = confClone[attr][key];
      if (typeof val === "string") {
        confClone[attr][key] = (event) => this.$emit(val, event);
      }
    });
  });
}

function buildDataObject(confClone, dataObject) {
  Object.keys(confClone).forEach((key) => {
    const val = confClone[key];
    if (key === "__vModel__") {
      vModel.call(this, dataObject, confClone.__config__.defaultValue);
    } else if (dataObject[key] !== undefined) {
      if (
        dataObject[key] === null ||
        dataObject[key] instanceof RegExp ||
        ["boolean", "string", "number", "function"].includes(
          typeof dataObject[key]
        )
      ) {
        dataObject[key] = val;
      } else if (Array.isArray(dataObject[key])) {
        dataObject[key] = [...dataObject[key], ...val];
      } else {
        dataObject[key] = { ...dataObject[key], ...val };
      }
    } else {
      dataObject.attrs[key] = val;
    }
  });

  // 清理属性
  clearAttrs(dataObject);
}

function clearAttrs(dataObject) {
  delete dataObject.attrs.__config__;
  delete dataObject.attrs.__slot__;
  delete dataObject.attrs.__methods__;
}

function makeDataObject() {
  // 深入数据对象：
  // https://cn.vuejs.org/v2/guide/render-function.html#%E6%B7%B1%E5%85%A5%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1
  return {
    class: {},
    attrs: {},
    props: {},
    domProps: {},
    nativeOn: {},
    on: {},
    style: {},
    directives: [],
    scopedSlots: {},
    slot: null,
    key: null,
    ref: null,
    refInFor: true,
  };
}

// export default defineComponent({
//   name: "render",
//   props: {
//     conf: {
//       type: Object,
//       required: true,
//     },
//   },
//   setup(props, ctx) {
//     console.log(props);
//     console.log(ctx);
//     const dataObject = makeDataObject();
//     const confClone = deepClone(props.conf);
//     const children = [ctx.slots.default] || [];
//     // 如果slots文件夹存在与当前tag同名的文件，则执行文件中的代码
//     mountSlotFiles.call(this, h, confClone, children);

//     // 将字符串类型的事件，发送为消息
//     emitEvents.call(this, confClone);

//     // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
//     buildDataObject.call(this, confClone, dataObject);
//     const Tag = props.conf.__config__.tag;
//     return <Tag></Tag>;
//   },
// });

export default defineComponent({
  name: "render",
  props: {
    conf: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      arr: [],
      tempTime: "",
    };
  },
  emits: ["input"],
  // setup(props, { slots, emit }) {
  //   const dataObject = makeDataObject();
  //   const confClone = deepClone(props.conf);
  //   // const children = [this.$slots.default] || [];
  //   console.log(slots, "slots");
  //   const children = [];
  //   // 如果slots文件夹存在与当前tag同名的文件，则执行文件中的代码
  //   mountSlotFiles(h, confClone, children);

  //   // 将字符串类型的事件，发送为消息
  //   emitEvents(emit, confClone);
  //   setTimeout(() => {
  //     emit("input", "4ww3243");
  //   }, 3000);
  //   // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
  //   const update = (val) => {
  //     console.log(val, "update");
  //     emit("input", val);
  //   };
  //   buildDataObject(update, confClone, dataObject);

  //   const Tag = formComponentsMap[props.conf.__config__.tag];

  //   return () => (
  //     <Tag
  //       {...dataObject.attrs}
  //       on={dataObject.on}
  //       modelValue={confClone.__config__.defaultValue}
  //     >
  //       {children}
  //     </Tag>
  //   );
  // },
  render() {
    const dataObject = makeDataObject();
    const confClone = deepClone(this.$props.conf);
    const children = [];
    // 如果slots文件夹存在与当前tag同名的文件，则执行文件中的代码
    mountSlotFiles(confClone, children);
    // 将字符串类型的事件，发送为消息
    emitEvents.call(this, confClone);

    // 将json表单配置转化为vue render可以识别的 “数据对象（dataObject）”
    buildDataObject.call(this, confClone, dataObject);
    const Tag = formComponentsMap[this.$props.conf.__config__.tag];

    // return h(Tag, dataObject.attrs, children);
    return (
      <>
        {children.length > 0 ? (
          <Tag
            {...dataObject.attrs}
            on={dataObject.on}
            v-model={this.$props.conf.__config__.defaultValue}
          >
            {children}
          </Tag>
        ) : (
          <Tag
            {...dataObject.attrs}
            on={dataObject.on}
            v-model={this.$props.conf.__config__.defaultValue}
          ></Tag>
        )}
      </>

      // <Tag options={dataObject.attrs.options} />
    );
  },
  // render() {

  //   return (
  //     <>
  //       {tag == "el-input" ? (
  //         <el-input
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         >
  //           {children}
  //         </el-input>
  //       ) : tag == "el-input-number" ? (
  //         <el-input-number
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         >
  //           {children}
  //         </el-input-number>
  //       ) : tag == "el-slider" ? (
  //         <el-slider
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         >
  //           {children}
  //         </el-slider>
  //       ) : tag == "el-time-picker" ? (
  //         <el-date-picker
  //           type="datetimerange"
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         />
  //       ) : tag === "el-switch" ? (
  //         <el-switch
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         ></el-switch>
  //       ) : tag === "el-color-picker" ? (
  //         <el-color-picker
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         ></el-color-picker>
  //       ) : tag === "el-button" ? (
  //         <el-button
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         >
  //           {children[1]}
  //         </el-button>
  //       ) : tag === "el-select" ? (
  //         <el-select
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         >
  //           {children}
  //         </el-select>
  //       ) : tag === "el-date-picker" ? (
  //         <el-date-picker
  //           {...dataObject.attrs}
  //           on={dataObject.on}
  //           modelValue={confClone.__config__.defaultValue}
  //         >
  //           {children}
  //         </el-date-picker>
  //       ) : null}
  //     </>
  //   );
  // },
});
