<template>
  <div ref="wrapRef" :class="getWrapperClass">
    <div
      :style="{
        height: '100%',
      }"
    >
      <FormItemRest>
        <a-table
          :id="'table' + madomkey"
          ref="tableElRef"
          v-bind="getBindValues"
          :rowClassName="getRowClassName"
          v-show="getEmptyDataIsShowTable"
          :showSorterTooltip="false"
          @change="handleTableChange"
          @resize-column="handleResizeColumn"
        >
          <template #summary v-if="columns.filter((x) => x.total).length > 0">
            <a-table-summary-row>
              <a-table-summary-cell>合计</a-table-summary-cell>
              <a-table-summary-cell v-if="getBindValues.rowSelection" />
              <a-table-summary-cell
                v-for="(column, idx) in columns.filter((x) => {
                  return !getBindValues.showIndexColumn
                    ? x.flag !== 'ACTION'
                    : x.flag !== 'INDEX' && x.flag !== 'ACTION';
                })"
                :key="idx"
                :style="{ textAlign: column.align }"
              >
                <a-typography-text v-if="column.total" keyboard>
                  {{ getColumnTotal(column.dataIndex) }}
                </a-typography-text>
              </a-table-summary-cell>
              <a-table-summary-cell v-if="getBindValues.actionColumn" />
            </a-table-summary-row>
          </template>
          <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
            <slot :name="item" v-bind="data || {}"></slot>
          </template>

          <template #bodyCell="data">
            <template v-for="item in Object.keys($slots)">
              <slot
                v-if="data.column && data.column.dataIndex && data.column.dataIndex === item"
                :name="item"
                v-bind="data || {}"
              ></slot>
            </template>
          </template>

          <template #headerCell="{ column }">
            <HeaderCell :column="column" />
          </template>
          <!-- <template #emptyText>
          <div class="ant-empty-image">
            <svg class="ant-empty-img-simple" width="64" height="20" viewBox="0 0 64 20">
              <g transform="translate(0 1)" fill="none" fill-rule="evenodd">
                <ellipse
                  class="ant-empty-img-simple-ellipse"
                  fill="#F5F5F5"
                  cx="32"
                  cy="33"
                  rx="32"
                  ry="7"
                />
                <g class="ant-empty-img-simple-g" fill-rule="nonzero" stroke="#D9D9D9">
                  <path
                    d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
                  />
                  <path
                    d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
                    fill="#FAFAFA"
                    class="ant-empty-img-simple-path"
                  />
                </g>
              </g>
            </svg>
          </div>
          <p>{{ t('暂无数据') }}</p>
        </template> -->
          <!--      <template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index">-->
          <!--        <HeaderCell :column="column" />-->
          <!--      </template>-->
        </a-table>
      </FormItemRest>
    </div>
  </div>
</template>
<script lang="ts">
  import type {
    BasicTableProps,
    TableActionType,
    SizeType,
    ColumnChangeParam,
  } from './types/table';

  import {
    defineComponent,
    ref,
    computed,
    unref,
    toRaw,
    inject,
    watchEffect,
    onMounted,
    watch,
    nextTick,
    // nextTick,
  } from 'vue';
  import { useForm } from '/@/components/Form/index';
  import { PageWrapperFixedHeightKey } from '/@/components/Page';
  import HeaderCell from './components/HeaderCell.vue';
  import { InnerHandlers } from './types/table';
  import { usePagination } from './hooks/usePagination';
  import { useColumns } from './hooks/useColumns';
  import { useDataSource } from './hooks/useDataSource';
  import { useLoading } from './hooks/useLoading';
  import { useRowSelection } from './hooks/useRowSelection';
  import { useTableScroll } from './hooks/useTableScroll';
  import { useTableScrollTo } from './hooks/useScrollTo';
  import { useCustomRow } from './hooks/useCustomRow';
  import { useTableStyle } from './hooks/useTableStyle';
  import { useTableHeader } from './hooks/useTableHeader';
  import { useTableExpand } from './hooks/useTableExpand';
  import { createTableContext } from './hooks/useTableContext';
  import { useTableFooter } from './hooks/useTableFooter';
  import { useTableForm } from './hooks/useTableForm';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
  import { omit } from 'lodash-es';
  import { basicProps } from './props';
  import { isFunction } from '/@/utils/is';
  import { warn } from '/@/utils/log';
  import { useI18n } from '/@/hooks/web/useI18n';
  import JBC from 'jsbi-calculator';
  import { Form } from 'ant-design-vue';
  import { formatter } from '/@/utils/event/design';

  const FormItemRest = Form.ItemRest;
  //   provide('isMenuTable', true);
  export default defineComponent({
    components: {
      HeaderCell,
      FormItemRest,
    },
    props: basicProps,
    emits: [
      'fetch-success',
      'fetch-error',
      'selection-change',
      'register',
      'row-click',
      'row-dbClick',
      'row-contextmenu',
      'row-mouseenter',
      'row-mouseleave',
      'edit-end',
      'edit-cancel',
      'edit-row-end',
      'edit-change',
      'expanded-rows-change',
      'change',
      'columns-change',
      'tree-show-change',
      'list-show-change',
      'redo',
    ],
    setup(props, { attrs, emit, slots, expose }) {
      const { t } = useI18n();
      const tableElRef = ref<any>(null);
      const tableData = ref<Recordable[]>([]);
      const wrapRef = ref(null);
      const formRef = ref();
      const innerPropsRef = ref<Partial<BasicTableProps>>();
      const { prefixCls } = useDesign('basic-table');
      const [registerForm, formActions] = useForm();
      const { calculator } = JBC;
      const { getRealWidth } = useMenuSetting();
      const getProps = computed(() => {
        return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
      });
      const madomkey = ref<string>(Math.random().toString(36).slice(-8));
      const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false);
      watchEffect(() => {
        unref(isFixedHeightPage) &&
          props.canResize &&
          warn(
            "'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight' (especially in hot updates)",
          );
      });
      watch(
        () => unref(getProps).rowResize,
        (val) => {
          handleResizeRow(val);
        },
      );
      function handleResizeRow(rowResize) {
        if (!rowResize) return;
        nextTick(() => {
          const table = document.getElementById('table' + madomkey.value);
          const rows: any = table?.querySelectorAll('.ant-table-row');
          for (const row of rows) {
            const resizable: any = row.getElementsByClassName('ant-table-cell');
            for (const item of resizable) {
              const handle = item.querySelector('.resize-handle');
              let originY, originHeight;

              handle?.addEventListener('mousedown', function (e) {
                originY = e.clientY;
                originHeight = item.offsetHeight;

                document.addEventListener('mousemove', resize);
                document.addEventListener('mouseup', stopResize);
              });

              function resize(e) {
                const height = originHeight + (e.clientY - originY);
                resizable[0].style.height = `${height}px`;
              }

              function stopResize() {
                document.removeEventListener('mousemove', resize);
                document.removeEventListener('mouseup', stopResize);
              }
            }
          }
        });
      }
      const { getLoading, setLoading } = useLoading(getProps);
      const {
        getPaginationInfo,
        getPagination,
        setPagination,
        setShowPagination,
        getShowPagination,
      } = usePagination(getProps);

      const {
        getRowSelection,
        getRowSelectionRef,
        getSelectRows,
        clearSelectedRowKeys,
        getSelectRowKeys,
        deleteSelectRowByKey,
        setSelectedRowKeys,
      } = useRowSelection(getProps, tableData, emit);

      const {
        handleTableChange: onTableChange,
        getDataSourceRef,
        getDataSource,
        getRawDataSource,
        setTableData,
        updateTableDataRecord,
        deleteTableDataRecord,
        insertTableDataRecord,
        findTableDataRecord,
        fetch,
        getRowKey,
        reload,
        updateTableColumn,
        getAutoCreateKey,
        updateTableData,
      } = useDataSource(
        getProps,
        {
          tableData,
          getPaginationInfo,
          setLoading,
          setPagination,
          getFieldsValue: formActions.getFieldsValue,
          clearSelectedRowKeys,
        },
        emit,
      );

      function handleTableChange(...args) {
        const { onChange, isPaginateByDataSource, isFilterByDataSoure } = unref(getProps);
        if (args[3].action === 'filter' && isFilterByDataSoure) return;

        onTableChange.call(undefined, isPaginateByDataSource, ...args);
        emit('change', { ...args[0], ...args[2] });

        // 解决通过useTable注册onChange时不起作用的问题
        onChange && isFunction(onChange) && onChange.call(undefined, ...args);
      }

      const {
        getViewColumns,
        getColumns,
        setCacheColumnsByField,
        setColumns,
        getColumnsRef,
        getCacheColumns,
        setMenuColumnConfig,
        getMenuColumnConfig,
      } = useColumns(getProps, getPaginationInfo);
      getMenuColumnConfig();
      const { getScrollRef, redoHeight, tabelWidth, headerHeight } = useTableScroll(
        getProps,
        tableElRef,
        getColumnsRef,
        getRowSelectionRef,
        getDataSourceRef,
        wrapRef,
        formRef,
      );

      const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef);

      const { customRow } = useCustomRow(getProps, {
        setSelectedRowKeys,
        getSelectRowKeys,
        clearSelectedRowKeys,
        getAutoCreateKey,
        emit,
      });

      const { getRowClassName } = useTableStyle(getProps, prefixCls);

      const { getExpandOption, expandAll, expandRows, collapseAll } = useTableExpand(
        getProps,
        tableData,
        emit,
      );
      //  const calcToolBarWidth = ref(0);
      const formShowPanel = ref(false);
      const handlers: InnerHandlers = {
        onColumnsChange: (data: ColumnChangeParam[], checkIndex: boolean, checkSelect: boolean) => {
          emit('columns-change', data, checkIndex, checkSelect);
          // support useTable
          unref(getProps).onColumnsChange?.(data);
        },
        onPanelShowChange: (value: boolean) => {
          formShowPanel.value = value;
          emit('list-show-change', value);
        },
        onTreeShowChange: (value: boolean) => {
          emit('tree-show-change', value, unref(headerHeight));
        },
        onRedo: () => {
          emit('redo');
        },
      };

      const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } =
        useTableForm(getProps, slots, fetch, getLoading);

      const getBindValues = computed(() => {
        const dataSource = unref(getDataSourceRef);
        let propsData: Recordable = {
          ...attrs,
          customRow,
          ...unref(getProps),
          ...unref(getHeaderProps),
          scroll: unref(getScrollRef),
          loading: unref(getLoading),
          tableLayout: 'fixed',
          rowSelection: unref(getRowSelectionRef),
          rowKey: unref(getRowKey),
          columns: toRaw(unref(getViewColumns)),
          pagination: toRaw(unref(getPaginationInfo)),
          dataSource,
          footer: unref(getFooterProps),
          ...unref(getExpandOption),
        };
        if (slots.expandedRowRender) {
          propsData = omit(propsData, 'scroll');
        }

        propsData = omit(propsData, ['class', 'onChange']);
        return propsData;
      });

      const { getFooterProps } = useTableFooter(
        getProps,
        getScrollRef,
        tableElRef,
        getDataSourceRef,
      );

      const getWrapperClass = computed(() => {
        const values = unref(getBindValues);
        let page = getShowPagination() ? prefixCls + '-form-has-pagenation' : '';
        let header = unref(getHasHeader) ? prefixCls + '-form-has-title' : '';
        // console.log(headerHeight, tabelWidth.value, calcToolBarWidth.value, 'headerHeight');
        let parallel = unref(headerHeight) > 62 ? prefixCls + '-form-has-parallel' : '';
        let showPanel = formShowPanel.value ? prefixCls + '-form-has-showPanel' : '';
        return [
          prefixCls,
          attrs.class,
          {
            [`${prefixCls}-form-container`]: values.useSearchForm,
            [`${prefixCls}--inset`]: values.inset,
          },
          page,
          header,
          parallel,
          showPanel,
        ];
      });
      const containerHeight = computed(() => {
        return `calc(100% - ${unref(headerHeight)}px)`;
      });
      const containerHeightTwo = computed(() => {
        return `calc(100% - ${unref(headerHeight) + 138 + 62}px)`;
      });
      const containerWidth = computed(() => {
        return `calc(100% - ${unref(getRealWidth) + 20}px)`;
      });
      const pageLeft = computed(() => {
        return `${unref(getRealWidth) + 10}px `;
      });
      const getEmptyDataIsShowTable = computed(() => {
        const { emptyDataIsShowTable, useSearchForm } = unref(getProps);
        if (emptyDataIsShowTable || !useSearchForm) {
          return true;
        }
        return !!unref(getDataSourceRef).length;
      });

      function setProps(props: Partial<BasicTableProps>) {
        innerPropsRef.value = { ...unref(innerPropsRef), ...props };
      }
      // const setToolBarWidth = () => {
      //   if (!tableElRef.value) return;
      //   calcToolBarWidth.value = tableElRef.value?.$el.querySelector(
      //     '.vben-basic-table-header__toolbar',
      //   )?.clientWidth;
      // };

      const getColumnTotal = (dataIndex) => {
        const numArr = getBindValues.value.dataSource.map((x) => Number(x[dataIndex as string]));
        if (numArr?.length) {
          return numArr.reduce((prev, cur) => {
            try {
              const func = new Function('return ' + `(${prev}+${cur})`);
              return Number(formatter(func().toFixed(4).toString(), 4));
            } catch (error) {}
          });
        }
        return 0;
      };

      onMounted(() => {
        // nextTick(() => {
        //   setToolBarWidth();
        // });
      });

      const tableAction: TableActionType = {
        reload,
        updateTableColumn,
        getSelectRows,
        clearSelectedRowKeys,
        getSelectRowKeys,
        deleteSelectRowByKey,
        setPagination,
        setTableData,
        updateTableDataRecord,
        deleteTableDataRecord,
        insertTableDataRecord,
        findTableDataRecord,
        redoHeight,
        setSelectedRowKeys,
        setColumns,
        setMenuColumnConfig,
        setLoading,
        getDataSource,
        getRawDataSource,
        setProps,
        getRowSelection,
        getPaginationRef: getPagination,
        getColumns,
        getCacheColumns,
        emit,
        updateTableData,
        setShowPagination,
        getShowPagination,
        setCacheColumnsByField,
        expandAll,
        expandRows,
        collapseAll,
        scrollTo,
        getSize: () => {
          return unref(getBindValues).size as SizeType;
        },
        // setToolBarWidth,
      };
      const { getHeaderProps, getHasHeader } = useTableHeader(
        getProps,
        slots,
        handlers,
        tabelWidth,
        getFormProps,
        getBindValues,
        tableAction,
        handleSearchInfoChange,
        redoHeight,
        getFormSlotKeys,
        replaceFormSlotKey,
        registerForm,
      );
      createTableContext({ ...tableAction, wrapRef, getBindValues });

      expose(tableAction);

      emit('register', tableAction, formActions);
      function handleResizeColumn(w, col) {
        col.width = w;
        updateTableColumn();
      }
      return {
        formRef,
        tableElRef,
        getBindValues,
        getLoading,
        registerForm,
        getEmptyDataIsShowTable,
        handleTableChange,
        getRowClassName,
        wrapRef,
        tableAction,
        getFormProps: getFormProps as any,
        getWrapperClass,
        columns: getViewColumns,
        t,
        tabelWidth,
        handleResizeColumn,
        calculator,
        getColumnTotal,
        containerHeight,
        containerHeightTwo,
        containerWidth,
        pageLeft,
        madomkey,
      };
    },
  });
</script>
<style lang="less">
  @border-color: #cecece4d;
  @tr-border-color: #6197ff;
  @img_bg: bg_img;

  @prefix-cls: ~'@{namespace}-basic-table';

  [data-theme='dark'] {
    .ant-table-tbody > tr:hover.ant-table-row-selected > td,
    .ant-table-tbody > tr.ant-table-row-selected td {
      background-color: #262626;
    }
  }

  .@{prefix-cls} {
    max-width: 100%;
    height: 100%;

    .header-cell__custom-title {
      height: 20px;
      margin: 15px 0;
      border-right: 1px solid #ddd;
      padding: 0 16px;
    }

    &-row__striped {
      td {
        background-color: @app-content-background;
      }
    }

    &-form-container {
      padding: 0;
      position: relative;

      .ant-form {
        &.search-form {
          position: absolute;
          padding-top: 0;
          z-index: 99;

          .ant-row {
            display: flex !important;
            flex: auto;
            justify-content: flex-end;
            align-items: center;
            line-height: 60px;
            margin-bottom: 0 !important;
          }
        }

        .basicCol {
          position: initial;
        }

        .ant-form-item-label {
          label {
            // max-width: 100px;
            overflow: hidden;
            text-overflow: ellipsis;
            display: block;
            line-height: 32px;
            margin-left: 16px;

            &::after {
              margin: 0 10px 0 0;
            }
          }
        }
      }
    }

    &-title {
      display: inline-block;
      width: 200px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      line-height: 60px !important;
      padding-left: 16px !important;
    }

    .ant-tag {
      margin-right: 0;
    }

    .ant-table-wrapper {
      height: 100%;

      .ant-spin-container {
        height: 100%;
      }

      .ant-table-title {
        padding: 0 !important;
      }

      .ant-table.ant-table-bordered .ant-table-title {
        border: none !important;
      }
    }

    .wrap {
      .ant-table-wrapper {
        padding: 0;
      }
    }

    .ant-table {
      width: 100%;
      overflow-x: hidden;
      height: 100%;
      background: none;
      // &.ant-table-layout-fixed {
      //   .ant-table-body {
      //     border-right: 1px solid #f0f0f0;
      //   }
      // }

      &-title {
        display: flex;
        padding: 8px 6px;
        border-bottom: none;
        justify-content: space-between;
        align-items: center;
      }

      &-container {
        height: 100%;
        background: #fff;
        border-radius: 16px;
      }

      &-content {
        max-height: none !important;
        height: 100%;
        overflow: auto;
      }

      &-thead {
        th {
          background: none;
          font-weight: bold;

          &::before {
            display: none;
          }

          .ant-table-column-sorters {
            display: block;
            position: relative;

            .ant-table-column-sorter {
              position: absolute;
              top: 2px;
              right: 6px;
              z-index: 2;
            }
          }
        }
      }

      &-body {
        // height: calc(100% - 51px) !important;
        max-height: none !important;

        .ant-table-summary {
          z-index: 0;
        }

        // table {
        //   height: 100%;
        // }
      }
      //.ant-table-tbody > tr.ant-table-row-selected td {
      //background-color: fade(@primary-color, 8%) !important;
      //}
      &-tbody {
        height: 100%;

        & > tr {
          & > td {
            padding: 0 8px !important;
            height: 50px;
            border-bottom: 1px solid #ddd;
            background: #fff;
          }

          &:hover {
            & > td {
              background: #f1f8ff;
            }
          }

          &.ant-table-expanded-row:hover > td {
            background: #fff;
          }

          &.ant-table-placeholder {
            .ant-table-expanded-row-fixed::after {
              display: none;
            }

            &:hover {
              td {
                background-color: transparent;
              }
            }
          }
        }
      }
    }

    &-form-has-pagenation {
      .ant-table {
        height: calc(100% - 52px);
        border-bottom: 1px solid rgb(238 238 238 / 93%);

        &-container {
          border-radius: 16px 16px 0 0;
        }
      }
    }

    &-form-has-title {
      .ant-table {
        &-container {
          height: calc(100% - 62px);
        }
      }
    }

    &-form-has-parallel {
      .ant-table {
        &-container {
          height: v-bind('containerHeight');
        }
      }
    }

    &-form-has-showPanel {
      .ant-table {
        &-container {
          position: fixed;
          bottom: 62px;
          right: 10px;
          width: v-bind('containerWidth');
          z-index: 100;
          height: v-bind('containerHeightTwo');
          box-shadow: 0 0 10px 0 rgb(0 0 0 / 20%);
        }
      }

      .ant-pagination {
        box-shadow: 0 0 10px 0 rgb(0 0 0 / 20%);
        position: fixed;
        right: 10px;
        bottom: 10px;
        z-index: 1000;
        left: v-bind('pageLeft');
      }
    }

    .ant-pagination {
      margin: 0;
      padding: 10px 6px 10px 0;
      background: #fff;
      border-radius: 0 0 16px 16px;
    }

    .ant-table-footer {
      padding: 0;

      .ant-table-wrapper {
        padding: 0;
      }

      table {
        border: none !important;
      }

      .ant-table-body {
        overflow-x: hidden !important;
        //  overflow-y: scroll !important;
      }

      td {
        padding: 12px 8px;
      }
    }

    &--inset {
      .ant-table-wrapper {
        padding: 0;
      }
    }
  }

  .resize-handle {
    width: 100%;
    height: 1px;
    right: 0;
    bottom: 0;
    cursor: row-resize;
    border-top: 1px solid #1c8dff;
    position: absolute;
    opacity: 0;
  }

  tr:hover {
    .resize-handle {
      opacity: 1;
    }
  }
</style>
