<template>
  <div class="widget-item-container" :style="{ height: level === 1 ? 'inherit' : 'auto' }">
    <div
      class="widget-view"
      :id="'widget-view' + element.key + random"
      v-if="element"
      :key="element.key"
      :class="{
        active: selectWidget?.key === element.key,
      }"
      :style="{
        height: level === 1 ? 'inherit' : 'auto',
        padding: preview ? '0' : '16px',
        margin: preview ? '0' : '2px 2px 10px',
      }"
    >
      <template v-if="element.type === 'vertical'">
        <VerticalLayout
          class="widget-col"
          v-if="element.key"
          :key="element.key"
          :active="selectWidget?.key === element.key"
          :config="element"
          :level="level"
          @add-content="handleContent"
          @add-sider="handleSider"
          @con-scroll="handleScroll"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'horizontal'">
        <HorizontalLayout
          class="widget-col"
          v-if="element.key"
          :key="element.key"
          :active="selectWidget?.key === element.key"
          :config="element"
          :level="level"
          @add-content="handleContent"
          @add-header="handleHeader"
          @add-footer="handleFooter"
          @con-scroll="handleScroll"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'normal'">
        <NormalLayout
          class="widget-col"
          v-if="element.key"
          :key="element.key"
          :active="selectWidget?.key === element.key"
          :config="element"
          :level="level"
          @add-content="handleContent"
          @add-sider="handleSider"
          @add-footer="handleFooter"
          @con-scroll="handleScroll"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'collapse'">
        <CollapseLayout
          class="widget-col"
          v-if="element.key"
          :key="element.key"
          :active="selectWidget?.key === element.key"
          :config="element"
          @add-collapse="handleCollapse"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'panel'">
        <CollapseLayout
          class="widget-col"
          v-if="element.key"
          :key="element.key"
          :active="selectWidget?.key === element.key"
          :config="element"
          @add-collapse="handleCollapse"
          @click.stop="handleItemClick(element)"
        />
      </template>

      <template v-if="element.type === 'tab'">
        <div
          class="widget-col"
          type="flex"
          v-if="element.key"
          :key="element.key"
          :class="{ active: selectWidget?.key === element.key }"
          :gutter="element.options.gutter ?? 0"
          :justify="element.options.justify"
          :align="element.options.align"
          @click.stop="handleItemClick(element)"
        >
          <a-tabs
            style="width: 100%"
            :type="element.options.type"
            :tab-position="element.options.tabPosition"
            v-model:activeKey="activeKey"
            :id="`tabs-${element.key}`"
            @change="handleTabsChange"
          >
            <a-tab-pane v-for="(col, colIndex) of element.layout" :key="colIndex">
              <template #tab>
                <div :style="`background: url(${col.imageUrl}) no-repeat`">
                  <Icon :icon="col.prefix" v-if="col.prefix" />
                  <span
                    :style="`color:${
                      activeKey == colIndex ? col.activeColor : 'rgba(0, 0, 0, 0.85)'
                    }`"
                    >{{ col.name }}</span
                  >
                  <Icon :icon="col.suffix" v-if="col.suffix" class="!mr-0 ml-3" />
                </div>
              </template>
              <DraggableItem
                :list="col.list"
                :style="`background: url(${col.conImageUrl}) no-repeat`"
                @add="
                  (e) => {
                    handleTableAdd(e, col.list);
                  }
                "
                @copy="
                  (e) => {
                    handleTableCopy(e, col.list);
                  }
                "
                @delete="
                  (e) => {
                    handleTableDelete(e, col.list);
                  }
                "
              />
            </a-tab-pane>
          </a-tabs>
        </div>
      </template>

      <template v-if="element.type === 'iframe'">
        <!-- iframe 传值 -->
        <IframeComponent
          :url="element.options.url"
          :list="element.options.list"
          :width="element.options.width"
          :height="element.options.height"
          :label="element.options.label"
          :key="refreshFieldObj[element.key]"
          @click.stop="handleItemClick(element)"
        />
      </template>

      <template v-if="element.type === 'table-layout'">
        <TableLayout
          :element="element"
          @click="handleTableLayoutClick(element)"
          :key="element.key"
          @con-scroll="handleScroll"
        >
          <template #tdElement="{ tdElement }">
            <div class="h-full">
              <DraggableItem
                :list="tdElement.children"
                :tableConfig="tdElement"
                @add="
                  (e) => {
                    handleTableAdd(e, tdElement.children);
                  }
                "
                @copy="
                  (e) => {
                    handleTableCopy(e, tdElement.children);
                  }
                "
                @delete="
                  (e) => {
                    handleTableDelete(e, tdElement.children);
                  }
                "
              />
            </div>
          </template>
        </TableLayout>
      </template>
      <template v-if="element.type === 'tree'">
        <TreeComponent
          :treeConfig="element.options.treeConfig"
          :apiConfig="element.options.apiConfig"
          :title="element.options.label"
          :showLabel="element.options.showLabel"
          :options="element.options"
          v-bind="getComponentsProps"
          :compkey="element.key"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'search'">
        <SearchComponent
          :schemas="element.options.schemas"
          :fieldMapToTime="element.options.fieldMapToTime"
          :tableWidth="searchTotalWidth[random]"
          :compkey="element.key"
          v-bind="getComponentsProps"
          :key="refreshFieldObj[element.key]"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'list'">
        <TableComponent
          :config="element.options"
          :compkey="element.key"
          :key="refreshFieldObj[element.key]"
          v-bind="getComponentsProps"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'form'">
        <FormComponent
          :config="element.options"
          :compkey="element.key"
          :key="refreshFieldObj[element.key]"
          v-bind="getComponentsProps"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'chart'">
        <ChartComponent
          :compkey="element.key"
          :refreshkey="refreshFieldObj[element.key]"
          :config="element.options"
          @click.stop="handleItemClick(element)"
        />
      </template>
      <template v-if="element.type === 'button'">
        <ButtonComponent :list="element.options.buttons" @click.stop="handleItemClick(element)" />
      </template>
    </div>
    <div
      class="widget-view-action"
      :class="{
        'widget-col-action': element.type === 'grid',
      }"
      v-if="selectWidget?.key === element.key && !preview"
    >
      <a-popover placement="top" v-if="element.type === 'table-layout'">
        <template #content>
          <span>添加行</span>
        </template>
        <span class="svgicon">
          <IconFontSymbol icon="jiahao" @click.stop="emit('addRow')" />
        </span>
      </a-popover>
      <a-popover placement="top" v-if="element.type === 'table-layout'">
        <template #content>
          <span>添加列</span>
        </template>
        <span class="svgicon">
          <IconFontSymbol icon="jiahao" @click.stop="emit('addCol')" />
        </span>
      </a-popover>
      <span class="svgicon">
        <IconFontSymbol icon="fuzhi" @click.stop="emit('copy')" />
      </span>
      <span class="svgicon icon-delete">
        <IconFontSymbol icon="shanchu" @click.stop="emit('delete')" />
      </span>
      <span class="svgicon">
        <IconFontSymbol icon="yidong" className="drag-widget" />
      </span>
    </div>
  </div>
</template>

<script setup lang="ts" name="widgetFormItem">
  import { inject, watch, ref, onMounted, toRaw, computed, createVNode, unref } from 'vue';
  import TableLayout from './components/TableLayout.vue';
  import { Icon } from '/@/components/Icon';
  import VerticalLayout from './components/verticalLayout.vue';
  import HorizontalLayout from './components/horizontalLayout.vue';
  import NormalLayout from './components/normalLayout.vue';
  import DraggableItem from './components/draggableItem.vue';
  import IframeComponent from './components/iframeComponent.vue';
  import ChartComponent from './components/chartComponent.vue';
  import TableComponent from './components/tableComponent.vue';
  import FormComponent from './components/formComponent.vue';
  import TreeComponent from './components/TreeComponent.vue';
  import ButtonComponent from './components/buttonComponent.vue';

  import { useUserStore } from '/@/store/modules/user';
  import { buildShortUUID, buildUUID } from '/@/utils/uuid';
  import { useMessage } from '/@/hooks/web/useMessage';

  import IconFontSymbol from '/@/components/IconFontSymbol/Index.vue';
  import { getFileList } from '/@/api/system/file';
  import { cloneDeep, upperFirst } from 'lodash-es';
  import CollapseLayout from './components/collapseLayout.vue';
  import SearchComponent from './components/searchComponent.vue';
  import { defHttp } from '/@/utils/http/axios';
  import { regTestProps, requestProps } from '/@/components/Form/src/types/form';
  import { message, Modal, ModalFuncProps } from 'ant-design-vue';
  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
  const userStore = useUserStore();

  const props = defineProps({
    element: {
      type: Object,
      required: true,
    },

    labelCol: {
      type: Object,
      default: () => {},
    },
    childIndex: {
      type: Number,
    },
    level: Number,
  });
  const emit = defineEmits([
    'copy',
    'delete',
    'update:widgetFormSelect',
    'addRow',
    'addCol',
    'addContent',
    'addSider',
    'addHeader',
    'addFooter',
    'addCollapse',
    'clickTable',
    'conScroll',
  ]);
  const selectWidget = inject('selectWidget', ref<any>({}));
  const refreshFieldObj = inject('refreshFieldObj', ref<any>({}));
  let preview = inject('preview') as boolean;
  let previewVisible = inject('previewVisible') as boolean;

  const widgetForm = inject('widgetForm', ref<any>([]));
  const random = buildShortUUID();
  const searchTotalWidth = ref({});

  const { notification } = useMessage();
  const activeKey = ref<number>(0);

  watch(
    () => selectWidget.value,
    () => {},
    { deep: true },
  );
  watch(
    () => unref(previewVisible),
    (val) => {
      if (!val) unref(refreshFieldObj)[props.element.key]++;
    },
  );
  const handleTableAdd = (event: any, list: any) => {
    const newlist = JSON.parse(JSON.stringify(list));
    const { newIndex } = event;

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

    newlist[newIndex] = {
      ...toRaw(newlist[newIndex]),
      key,
    };

    list.splice(newIndex, 1, newlist[newIndex]);

    //selectWidget.value = newlist[newIndex];
  };
  function handleTableCopy(obj: any, list: any) {
    const key = buildUUID().replaceAll('-', '');
    let newobj = {
      ...toRaw(cloneDeep(obj)),
      key,
    };
    list.push(newobj);
  }
  function handleTableDelete(idx, list) {
    list.splice(idx, 1);
  }
  watch(
    () => props.element,
    (val) => {
      if (val.type == 'tab') {
        handleTabsChange(activeKey.value);
        val.layout.forEach((o) => {
          getTabImages(o);
        });
      }
      if (val.type == 'search') {
        unref(refreshFieldObj)[props.element.key] = 1;
      }
      compulateSearchWidth(val);
    },
    {
      deep: true,
    },
  );
  onMounted(() => {
    if (props.element.type == 'tab') {
      handleTabsChange(0);
      props.element.layout.forEach((o) => {
        getTabImages(o);
      });
    }
    compulateSearchWidth(props.element);
    window.addEventListener('resize', () => {
      compulateSearchWidth(props.element);
    });
  });
  function compulateSearchWidth(element) {
    if (element.type == 'search') {
      let parant = document.getElementById('widget-view' + element.key + random);
      let width = parant?.querySelector('.ant-form')?.clientWidth;
      searchTotalWidth.value[random] = width || 0;
    }
  }
  const getComponentsProps = computed(() => {
    let { options = {} } = props.element;

    if (options['events']) {
      for (const eventKey in options['events']) {
        try {
          const event = new Function(
            'schema',
            'formActionType',
            'eventData',
            'options',
            `${options['events'][eventKey]}`,
          );

          options['on' + upperFirst(eventKey)] = function (e, opt) {
            event(props.element, formApi, e, opt);
          };
        } catch (error) {
          notification.error({
            message: 'Tip',
            description: '触发事件填写有误！',
          });
        }
      }
    }

    return options as Recordable;
  });
  function getTabImages(o) {
    if (o.folderId) {
      getFileList({ folderId: o.folderId }).then((fileList) => {
        if (fileList.length) {
          o.imageUrl = fileList[0].fileUrl;
        }
      });
    }
    if (o.conFolderId) {
      getFileList({ folderId: o.conFolderId }).then((fileList) => {
        if (fileList.length) {
          o.conImageUrl = fileList[0].fileUrl;
        }
      });
    }
  }
  function handleContent(list) {
    emit('addContent', list);
  }
  function handleSider(list) {
    emit('addSider', list);
  }
  function handleHeader(list) {
    emit('addHeader', list);
  }
  function handleFooter(list) {
    emit('addFooter', list);
  }
  function handleCollapse(list) {
    emit('addCollapse', list);
  }
  function handleScroll(e) {
    emit('conScroll', e);
  }
  const handleItemClick = (row: any) => {
    if (preview) return;
    selectWidget.value = row;
  };
  const handleTableLayoutClick = (row: any) => {
    if (preview) return;
    selectWidget.value = row;

    emit('clickTable');
  };

  function handleTabsChange(idx) {
    if (document.getElementById('tabs-' + props.element.key)) {
      document
        .getElementById('tabs-' + props.element.key)
        .querySelector('.ant-tabs-ink-bar').style.background =
        props.element.layout[idx].activeColor || primaryColor;
    }
  }

  const showModal = async (modal: ModalFuncProps) => {
    Modal.confirm({
      title: modal.title,
      icon: createVNode(ExclamationCircleOutlined),
      content: createVNode('div', { style: 'color:red;' }, modal.content),
      onOk: modal.onOk,
      onCancel: modal.onCancel,
      ...modal,
    });
  };

  const showMessage = (content: string) => {
    message.info(content);
  };

  const getUserInfo = (info: string) => {
    if (info === 'roleId') {
      return userStore.getUserInfo.roles.length && userStore.getUserInfo.roles[0].id;
    }
    return userStore.getUserInfo[info];
  };

  const regTest = async (regular: regTestProps) => {
    const regExpression = regular.regExpression;
    const testRes = regExpression.test(regular.testValue);
    testRes ? message.success(regular.successMessage) : message.error(regular.errorMessage);
  };

  const httpRequest = async (request: requestProps) => {
    if (request.requestType.toLowerCase() === 'get') {
      return defHttp[request.requestType](
        {
          url: request.requestUrl,
          params: request.params,
          ...request,
        },
        {
          errorMessageMode: request.errorMessageMode || 'none',
          ...request,
        },
      );
    } else {
      return defHttp[request.requestType](
        {
          url: request.requestUrl,
          data: request.params,
          ...request,
        },
        {
          errorMessageMode: request.errorMessageMode || 'none',
          ...request,
        },
      );
    }
  };

  const refreshAPI = (field: string) => {
    if (!field) return;

    if (!Object.keys(unref(refreshFieldObj)).includes(field)) {
      unref(refreshFieldObj)[field] = 0;
    }
    unref(refreshFieldObj)[field]++;
  };

  const changeStyle = (schema, style, field?) => {
    if (field) {
      schema = findSchema(unref(widgetForm), field);
    }
    schema.options.style = { ...schema.options.style, ...style };
  };
  const findSchema = (list, key) => {
    let schema;
    list?.some((info) => {
      if (['vertical', 'horizontal', 'normal', 'collapse', 'panel', 'tab'].includes(info.type)) {
        const hasComponent = info.layout.some((childInfo) => {
          schema = childInfo.list.find((com) => {
            let field = com.field || com.key;
            return field === key;
          });
          if (!!schema) return true;
          schema = findSchema(childInfo.list, key);
          return !!schema;
        });
        return !!hasComponent;
      } else if (info.type === 'table-layout') {
        const hasComponent = info.layout.some((childInfo) => {
          return childInfo.list.some((chil) => {
            schema = chil.children.find((com) => {
              let field = com.field || com.key;
              return field === key;
            });
            if (!!schema) return true;
            schema = findSchema(chil.children, key);
            return !!schema;
          });
        });
        return !!hasComponent;
      } else {
        schema = info.field || info.key === key ? info : null;
        return !!schema;
      }
    });
    return schema;
  };
  const formApi = {
    showModal,
    regTest,
    httpRequest,
    refreshAPI,
    changeStyle,
    showMessage,
    getUserInfo,
  };
</script>
<style scoped lang="less">
  .widget-item-container {
    height: inherit;
    position: relative;
  }

  .widget-item-container .widget-view {
    cursor: pointer;
    height: inherit;
  }

  .widget-item-container > div.active {
    background: #f7fbff;
    border: 1px dashed #1c8dff;
    border-radius: 4px;
  }

  .widget-view-action {
    display: flex;
    position: absolute;
    top: -12px;
    right: 12px;
  }

  .svgicon {
    color: @primary-color;
    border: 1px solid @primary-color;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    margin-left: 10px;
  }

  .svgicon svg {
    width: 14px !important;
    height: 14px !important;
  }

  .icon-delete {
    border: 1px solid #f64c4c;
    color: #f64c4c;
  }

  .radio-default {
    display: inline-block !important;
  }

  .radio-button {
    flex-wrap: wrap;
  }

  :deep(.ant-form-item-control-input-content .ant-radio-group .ant-radio-button-wrapper) {
    padding: 3px 7px !important;
    flex: auto;
  }

  // :deep(.ant-form-item-label > label) {
  //   white-space: normal;
  //   display: inline;
  //   line-height: 28px;
  //   cursor: pointer;
  // }

  .fc-style .widget-form-container .widget-form-list .widget-col-list {
    min-height: 100px;
    border: 1px dashed #ccc;
    background: #fff;
  }
</style>
