<script lang="ts" setup>
import type { Ref } from 'vue';

import type { Recordable } from '@vben/types';

import type { IFormConfig, IFormDesignMethods, IVFormComponent } from './types';

import { onMounted, provide, reactive, ref } from 'vue';

import { cloneDeep } from '@vben/utils';

import { Card, Collapse, Tabs } from 'ant-design-vue';

import ControlConfig from './components/control-config.vue';
import ControlMark from './components/control-mark.vue';
import FormConfig from './components/form-config.vue';
import FormEdit from './components/form-edit.vue';
import { basicControls } from './config/formItemProps';
import { generateKey } from './utils';

defineOptions({
  name: 'FormDesign',
});

const formConfig = ref<IFormConfig>({
  config: {
    wrapperClass: 'grid-cols-1',
    showDefaultActions: false,
    commonConfig: {
      labelWidth: 100,
    },
  },
  schemas: [],
  currentItem: { component: '' } as IVFormComponent,
});

const state = reactive<{
  collapseKey: string;
  controlList: Recordable<any>[];
}>({
  collapseKey: '1',
  controlList: [
    {
      title: '输入型组件',
      fields: ['Input', 'Textarea', 'InputPassword', 'InputNumber'],
      list: basicControls,
    },
  ],
});

/**
 * 选中表单项
 * @param schema 当前选中的表单项
 */
const handleSetSelectItem = (schema: IVFormComponent) => {
  formConfig.value.currentItem = schema as any;
  // handleChangePropsTabs(
  //   schema.key ? (formConfig.value.activeKey! === 1 ? 2 : formConfig.value.activeKey!) : 1,
  // );
};

const setGlobalConfigState = (formItem: IVFormComponent) => {
  // formItem.colProps = formItem.colProps || {};
  // formItem.colProps.span = globalConfigState.span;
  formItem.aaa = '';
  // console.log('setGlobalConfigState', formItem);
};

// 把表单配置项注入到子组件中，子组件可通过inject获取，获取到的数据为响应式
provide<Ref<IFormConfig>>('formConfig', formConfig as any);

/**
 * 添加属性
 * @param schemas
 * @param index
 */
const handleAddAttrs = (_formItems: IVFormComponent[], _index: number) => {};

const handleListPushDrag = (item: IVFormComponent) => {
  const formItem = cloneDeep(item);
  setGlobalConfigState(formItem);
  generateKey(formItem);

  return formItem;
};

/**
 * 添加到表单中
 * @param newIndex {object} 事件对象
 * @param schemas {IVFormComponent[]} 表单项列表
 * @param isCopy {boolean} 是否复制
 */
const handleBeforeColAdd = (
  { newIndex }: any,
  schemas: IVFormComponent[],
  isCopy = false,
) => {
  const item = schemas[newIndex] as IVFormComponent;
  isCopy && generateKey(item);
  handleSetSelectItem(item);
};
/**
 * 复制表单项，如果表单项为栅格布局，则遍历所有自表单项重新生成key
 * @param {IVFormComponent} formItem
 * @return {IVFormComponent}
 */
const copyFormItem = (formItem: IVFormComponent) => {
  const newFormItem = cloneDeep(formItem);
  // if (newFormItem.component === 'Grid') {
  //   formItemsForEach([formItem], (item) => {
  //     generateKey(item);
  //   });
  // }
  return newFormItem;
};
/**
 * 复制或者添加表单，isCopy为true时则复制表单
 * @param item {IVFormComponent} 当前点击的组件
 * @param isCopy {boolean} 是否复制
 */
const handleCopy = (
  item: IVFormComponent = formConfig.value.currentItem as IVFormComponent,
  isCopy = true,
) => {
  const key = formConfig.value.currentItem?.key;
  /**
   * 遍历当表单项配置，如果是复制，则复制一份表单项，如果不是复制，则直接添加到表单项中
   * @param schemas
   */
  const traverse = (schemas: IVFormComponent[]) => {
    // 使用some遍历，找到目标后停止遍历
    schemas.some((formItem: IVFormComponent, index: number) => {
      if (formItem.key === key) {
        // 判断是不是复制
        isCopy
          ? schemas.splice(index, 0, copyFormItem(formItem))
          : schemas.splice(index + 1, 0, item);
        const event = {
          newIndex: index + 1,
        };
        // 添加到表单项中
        handleBeforeColAdd(event, schemas, isCopy);
        return true;
      }
      return false;
    });
  };
  if (formConfig.value.schemas) {
    traverse(formConfig.value.schemas as any);
  }
};

/**
 * 单击控件时添加到面板中
 * @param item {IVFormComponent} 当前点击的组件
 */
const handleListPush = (item: IVFormComponent) => {
  // console.log('handleListPush', item);
  const formItem = cloneDeep(item);
  setGlobalConfigState(formItem);
  generateKey(formItem);
  if (!formConfig.value.currentItem?.key) {
    handleSetSelectItem(formItem);
    formConfig.value.schemas && formConfig.value.schemas.push(formItem as any);

    return;
  }
  handleCopy(formItem, false);
};

// 把祖先组件的方法项注入到子组件中，子组件可通过inject获取
provide<IFormDesignMethods>('formDesignMethods', {
  handleAddAttrs,
  handleSetSelectItem,
});

onMounted(async () => {});
</script>
<template>
  <div class="flex h-full w-full">
    <div class="w-[300px]">
      <Collapse
        :bordered="false"
        ghost
        expand-icon-position="end"
        v-model:active-key="state.collapseKey"
      >
        <Collapse.Panel
          v-for="(item, index) in state.controlList"
          :key="index + 1"
          :header="item.title"
        >
          <ControlMark
            :fields="item.fields"
            :list="item.list"
            @add-attrs="handleAddAttrs"
            :handle-list-push="handleListPushDrag"
            @handle-list-push="handleListPush"
          />
        </Collapse.Panel>
      </Collapse>
    </div>
    <div class="h-full flex-1 pl-2 pr-2">
      <Card title="设计区域" class="h-full w-full">
        <FormEdit
          :form-config="formConfig"
          :form-config-select="formConfig.currentItem"
          @change="handleSetSelectItem"
        />
      </Card>
    </div>
    <div class="w-[300px]">
      <Tabs>
        <Tabs.TabPane key="1" tab="组件属性">
          <ControlConfig />
        </Tabs.TabPane>
        <Tabs.TabPane key="2" tab="表单属性">
          <FormConfig v-model:config="formConfig.config" />
        </Tabs.TabPane>
      </Tabs>
    </div>
  </div>
</template>
