<template>
  <div class="awf-container-center">
    <div class="widget-form-container" ref="widgetFormRef">
      <div v-if="!widgetForm.list" class="form-empty">从左侧拖拽来添加字段</div>
      <a-form
        :layout="widgetForm.config.layout"
        :labelAlign="widgetForm.config.labelAlign"
        :labelCol="widgetForm.config.labelCol"
        :disabled="true"
      >
        <Draggable
          class="widget-form-list"
          item-key="key"
          ghostClass="ghost"
          handle=".drag-widget"
          :animation="200"
          :group="{ name: 'people' }"
          :list="widgetForm.list"
          @add="handleMoveAdd"
        >
          <template #item="{ element, index }">
            <transition-group name="fade" tag="div">
              <AntdWidgetFormItem
                v-if="element.key"
                :key="element.key"
                class="drag-widget"
                :element="element"
                :config="widgetForm.config"
                :selectWidget="widgetFormSelect"
                @click="handleItemClick(element)"
                @copy="handleCopyClick(index, widgetForm.list)"
                @delete="handleDeleteClick(index, widgetForm.list)"
                @addRow="handleAddClick(element, 'row')"
                @addCol="handleAddClick(element, 'col')"
              />
            </transition-group>
          </template>
        </Draggable>
      </a-form>
    </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent, nextTick, PropType, toRaw, inject, Ref, ref } from 'vue';
  import Draggable from 'vuedraggable';
  import AntdWidgetFormItem from './AntdWidgetFormItem.vue';
  import { SvgIcon } from '/@/components/Icon';
  import {
    WidgetForm,
    gridComponents,
    TableInfo,
    noHaveTableAndField,
    noHaveField,
    TableCell,
    TableTh,
  } from '../types';
  import { buildUUID } from '/@/utils/uuid';
  import { error } from '/@/utils/log';
  import { changeToPinyin } from '/@/utils/event/design';
  import { random } from 'lodash-es';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { useMessage } from '/@/hooks/web/useMessage';

  const handleListInsert = (key: string, list: any[], obj: any) => {
    const newList: any[] = [];
    list.forEach((item) => {
      if (item.key === key) {
        newList.push(item);
        newList.push(obj);
      } else {
        if (item.columns) {
          item.columns = item.columns.map((col: any) => ({
            ...col,
            list: handleListInsert(key, col.list, obj),
          }));
        }
        newList.push(item);
      }
    });
    return newList;
  };

  const handleListDelete = (key: string, list: any[]) => {
    const newList: any[] = [];
    list.forEach((item) => {
      if (item.key !== key) {
        if (item.columns) {
          item.columns = item.columns.map((col: any) => ({
            ...col,
            list: handleListDelete(key, col.list),
          }));
        }
        newList.push(item);
      }
    });
    return newList;
  };

  export default defineComponent({
    name: 'AntdWidgetForm',
    components: {
      SvgIcon,
      Draggable,
      AntdWidgetFormItem,
    },
    props: {
      widgetForm: {
        type: Object as PropType<WidgetForm>,
        required: true,
      },
      widgetFormSelect: {
        type: Object,
      },
    },
    emits: ['update:widgetForm', 'update:widgetFormSelect'],
    setup(props, context) {
      const { notification } = useMessage();
      const { t } = useI18n();
      const widgetFormRef = ref();

      const state = inject('state') as any;
      const tableInfo = inject<Ref<TableInfo[]>>('tableInfo') as Ref<TableInfo[]>;
      const isFieldUpper = inject<Ref<boolean>>('isFieldUpper', ref(false));
      const designType = inject('designType') as string;
      const tablecell = inject<Ref<TableCell>>('tableCell');
      const tableth = inject<Ref<TableTh>>('tableTh');
      let mainTableName;
      if (designType !== 'data') {
        mainTableName = inject<string>('mainTableName');
      }

      const handleItemClick = (row: any) => {
        state.widgetFormSelect = row;
        if (row.type === 'table-layout') {
          if (tablecell) tablecell.value = {};
          if (tableth) tableth.value = {};
        }
      };

      const handleAddClick = (row: any, type: string) => {
        let tdMax = 0;
        row.layout[0].list.forEach((o) => {
          if (o.colspan) {
            tdMax = tdMax + o.colspan;
          } else {
            tdMax += 1;
          }
        });
        if (type == 'row') {
          let lastRow: any = [];
          for (let j = 0; j < tdMax; j++) {
            lastRow.push({
              width: '',
              height: '',
              class: 'tableLayoutTd',
              children: [],
              position: [row.layout.length, j],
            });
          }
          row.layout.push({ list: lastRow });
        } else {
          row.layout.forEach((o, i) => {
            o.list.push({
              width: '',
              height: '',
              class: 'tableLayoutTd',
              children: [],
              position: [i, tdMax],
            });
          });
        }
      };
      const handleCopyClick = (index: number, list: any[]) => {
        const key = buildUUID().replaceAll('-', '');
        const oldList = JSON.parse(JSON.stringify(props.widgetForm.list));
        let copyData = {
          ...list[index],
          key,
          model: `${list[index].type}_${key}`,
          rules: list[index].rules ?? [],
          bindField: '',
        };

        if (
          list[index].type === 'radio' ||
          list[index].type === 'checkbox' ||
          list[index].type === 'select'
        ) {
          copyData = {
            ...copyData,
            options: {
              ...copyData.options,
              staticOptions: copyData.options.staticOptions.map((item: any) => ({ ...item })),
            },
          };
        }
        copyLayoutData([copyData], mainTableName);

        context.emit('update:widgetForm', {
          ...props.widgetForm,
          list: handleListInsert(list[index].key, oldList, copyData),
        });
        inject('widgetFormSelect', copyData);
        context.emit('update:widgetFormSelect', copyData);
      };

      const copyLayoutData = (data, tableName) => {
        data.map((item) => {
          if (['tab', 'grid', 'card'].includes(item.type)) {
            item.bindTable = '';
            item.key = buildUUID().replaceAll('-', '');
            addBindTableAndField(item, tableName);
            for (const child of item.layout!) {
              copyLayoutData(child.list, tableName);
            }
          } else if (item.type === 'table-layout') {
            item.bindTable = '';
            item.key = buildUUID().replaceAll('-', '');
            addBindTableAndField(item, tableName);
            for (const child of item.layout!) {
              for (const list of child.list!) {
                copyLayoutData(list.children, tableName);
              }
            }
          } else if (['form', 'one-for-one'].includes(item.type)) {
            item.key = buildUUID().replaceAll('-', '');
            addBindTableAndField(item);
            copyLayoutData(item.children, item.bindTable);
          } else {
            item.bindField = '';
            item.bindTable = tableName;
            item.key = buildUUID().replaceAll('-', '');
            addBindTableAndField(item, tableName);
          }
        });
      };

      const handleDeleteClick = async (index: number, list: any[]) => {
        await deleteAdoptedCalc(index, list);
        const oldList = JSON.parse(JSON.stringify(props.widgetForm.list));

        if (list.length - 1 === index) {
          if (index === 0) {
            nextTick(() => context.emit('update:widgetFormSelect', null));
          } else {
            context.emit('update:widgetFormSelect', list[index - 1]);
          }
        } else {
          context.emit('update:widgetFormSelect', list[index + 1]);
        }

        context.emit('update:widgetForm', {
          ...props.widgetForm,
          list: handleListDelete(list[index].key, oldList),
        });
      };

      const handleTabGridDeleteClick = (index: number, list: any[]) => {
        list.splice(index, 1);
      };

      const handleMoveAdd = (event: any) => {
        const list = JSON.parse(JSON.stringify(props.widgetForm.list));
        const { newIndex } = event;

        //判断如果是单表 不支持子表单组件 (仅数据优先时)
        if (tableInfo.value.length < 2 && list[newIndex].type === 'form' && designType === 'data') {
          list.splice(newIndex, 2); //必须2
          context.emit('update:widgetForm', { ...props.widgetForm, list });
          error('单表不能使用子表单组件！');
          return;
        }
        const key = buildUUID().replaceAll('-', '');

        list[newIndex] = {
          ...toRaw(list[newIndex]),
          key,
          model: `${list[newIndex].type}_${key}`,
          rules: [],
        };
        if (list[newIndex].type === 'sun-form') {
          list.splice(newIndex, 1);
          context.emit('update:widgetForm', { ...props.widgetForm, list });
          notification.error({
            message: t('提示'),
            description:
              '次级表格组件仅允许拖入表格组件当中，并且一个表格组件仅允许拖入一个次级表格组件，请确认后再拖入组件。',
          });
          return;
        }

        if (
          list[newIndex].type === 'radio' ||
          list[newIndex].type === 'checkbox' ||
          list[newIndex].type === 'select'
        ) {
          list[newIndex] = {
            ...list[newIndex],
            options: {
              ...list[newIndex].options,
              staticOptions: list[newIndex].options.staticOptions.map((item: any) => ({
                ...item,
              })),
            },
          };
        }

        if (list[newIndex].type === 'grid') {
          list[newIndex].layout.map((item: any) => (item.list = []));
        }

        if (list[newIndex].type === 'form') {
          list[newIndex].children.map((item: any) => (item.list = []));
        }

        if (list[newIndex].type === 'tab') {
          list[newIndex].layout.map((item: any) => (item.list = []));
        }
        //从子表拖入主表时
        list[newIndex].isSubFormChild = false;
        list[newIndex].isSingleFormChild = false;

        addBindTableAndField(list[newIndex]);

        context.emit('update:widgetForm', { ...props.widgetForm, list });
        context.emit('update:widgetFormSelect', list[newIndex]);
      };

      const handleColMoveAdd = (event: any, row: any, index: string | number | symbol) => {
        const { newIndex, oldIndex, item } = event;
        if (row.type === 'form') {
          const list = JSON.parse(JSON.stringify(props.widgetForm.list));

          if (item.className.includes('data-grid')) {
            item.tagName === 'DIV' && list.splice(oldIndex, 0, row.children[newIndex]);
            row.children[index].splice(newIndex, 1);
            return false;
          }

          const key = buildUUID().replaceAll('-', '');

          row.children[newIndex] = {
            ...toRaw(row.children[index]),
            key,
            model: `${row.children[newIndex].type}_${key}`,
            rules: [],
          };

          if (
            row.children[newIndex].type === 'radio' ||
            row.children[newIndex].type === 'checkbox' ||
            row.children[newIndex].type === 'select'
          ) {
            row.children[newIndex] = {
              ...row.children[newIndex],
              options: {
                ...row.children[newIndex].options,
                staticOptions: row.children[newIndex].options.staticOptions.map((item: any) => ({
                  ...item,
                })),
              },
            };
          }
          context.emit('update:widgetFormSelect', row.children[newIndex]);
        } else {
          const list = JSON.parse(JSON.stringify(props.widgetForm.list));

          if (item.className.includes('data-grid')) {
            item.tagName === 'DIV' && list.splice(oldIndex, 0, row.layout[index].list[newIndex]);
            row.layout[index].list.splice(newIndex, 1);
            return false;
          }

          const key = buildUUID().replaceAll('-', '');

          row.layout[index].list[newIndex] = {
            ...toRaw(row.layout[index].list[newIndex]),
            key,
            model: `${row.layout[index].list[newIndex].type}_${key}`,
            rules: [],
          };

          if (
            row.layout[index].list[newIndex].type === 'radio' ||
            row.layout[index].list[newIndex].type === 'checkbox' ||
            row.layout[index].list[newIndex].type === 'select'
          ) {
            row.layout[index].list[newIndex] = {
              ...row.layout[index].list[newIndex],
              options: {
                ...row.layout[index].list[newIndex].options,
                staticOptions: row.layout[index].list[newIndex].options.staticOptions.map(
                  (item: any) => ({
                    ...item,
                  }),
                ),
              },
            };
          }

          context.emit('update:widgetFormSelect', row.layout[index].list[newIndex]);
        }
      };
      const addBindTableAndField = (component: any, table?) => {
        //界面优先和简易模板
        if (designType !== 'data') {
          //需要绑定字段、组件没有绑定字段的情况下新增绑定字段
          const rangeComponents = ['time-range', 'date-range'];
          if (rangeComponents.includes(component.type)) {
            component.bindStartTime =
              changeToPinyin(component.label, isFieldUpper.value) + random(1000, 9999);
            component.bindEndTime =
              changeToPinyin(component.label, isFieldUpper.value) + random(1000, 9999);
          } else if (!noHaveField.includes(component.type) && !component.bindField) {
            component.bindField =
              changeToPinyin(component.label, isFieldUpper.value) + random(1000, 9999);
          }
          if (component.type === 'form' || component.type === 'one-for-one') {
            component.bindTable = isFieldUpper.value
              ? `${mainTableName.value}_CHILD_${random(1000, 9999)}`
              : `${mainTableName.value}_child_${random(1000, 9999)}`;
          } else if (component.type == 'modal' || !noHaveTableAndField.includes(component.type)) {
            component.bindTable = table || mainTableName.value;
          }
        }
        if (component.isGridChild) component.options.span = 7;
      };

      //删除引用已删除的财务组件的计算式配置
      const deleteAdoptedCalc = (index: number, list: any[]) => {
        const component = list[index];
        if (['computational', 'money-chinese'].includes(component.type)) {
          component.options.beAdoptedComponent?.map((key) => {
            getLayoutComponent(list, key);
          });
        }
      };

      const getLayoutComponent = (list, key) => {
        list?.map((item) => {
          if (['tab', 'grid', 'card'].includes(item.type)) {
            for (const child of item.layout!) {
              getLayoutComponent(child.list, key);
            }
          } else if (item.type === 'table-layout') {
            for (const child of item.layout!) {
              for (const list of child.list) {
                getLayoutComponent(list.children, key);
              }
            }
          } else if (item.type === 'form') {
            item.children.map((child: any) => {
              if (['computational', 'money-chinese'].includes(child.type) && child.key === key) {
                child.options.computationalConfig = [];
                child.options.computationalConfigValue = '== 请填写计算式配置 ==';
              }
            });
          } else {
            if (['computational', 'money-chinese'].includes(item.type) && item.key === key) {
              item.options.computationalConfig = [];
              item.options.computationalConfigValue = '== 请填写计算式配置 ==';
            }
          }
        });
      };

      return {
        handleItemClick,
        handleAddClick,
        handleCopyClick,
        handleDeleteClick,
        handleTabGridDeleteClick,
        handleMoveAdd,
        handleColMoveAdd,
        gridComponents,
        addBindTableAndField,
        widgetFormRef,
      };
    },
  });
</script>
<style scoped lang="less">
  /* @import '/@/assets/style/designer/index.css'; */
  .awf-container-center {
    width: 100%;
    padding: 0 10px;
    box-sizing: border-box;
  }

  .widget-form-container {
    width: 100%;
    background-color: #fff;
    padding: 20px 0;
    box-sizing: border-box;
  }

  .widget-form-list {
    //height: 100%;
  }

  .fc-style .widget-form-container .widget-form-list {
    background: #fff;
    // border: 1px dashed #999;
    min-height: calc(100vh - 305px);
  }
</style>
