import { GridModel } from '@ibiz-template/model';
import { useGridController, useNamespace } from '@ibiz-template/vue-util';
import {
  computed,
  defineComponent,
  getCurrentInstance,
  h,
  onUnmounted,
  PropType,
  Ref,
  ref,
  watch,
} from 'vue';
import { IModal } from '@ibiz-template/runtime';
import { AppGridPagination } from '@/components/common';
import {
  useAppGridPagination,
  useITableColumns,
  useITableEvent,
} from './grid-control.util';
import '@ibiz-template/theme/style/components/widgets/grid/grid.scss';

export const GridControl = defineComponent({
  props: {
    modelData: GridModel,
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    /**
     * 表格行数据默认激活模式
     * - 0 不激活
     * - 1 单击激活
     * - 2 双击激活(默认值)
     *
     * @type {(number | 0 | 1 | 2)}
     */
    gridRowActiveMode: { type: Number, default: 2 },
    modal: { type: Object as PropType<IModal> },
  },
  setup(props) {
    const { proxy } = getCurrentInstance()!;

    const ns = useNamespace('grid');
    const c = useGridController(
      proxy,
      props.modelData!,
      props.context!,
      props.params,
    );

    const [columns] = useITableColumns(c);
    const { onRowClick, onDbRowClick, onSelectionChange, onSortChange } =
      useITableEvent(c);
    const { onPageChange, onPageReset, onPageSizeChange } =
      useAppGridPagination(c);

    // iView表格单击行选中没有，必须手动调用选中方法
    const onUIRowClick = (data: IData, index: number) => {
      const gridInstance: IData | undefined = proxy.$refs.grid;
      if (gridInstance) {
        if (gridInstance.toggleSelect) {
          gridInstance.toggleSelect(index);
        }
        if (gridInstance.highlightCurrentRow) {
          gridInstance.highlightCurrentRow(index);
        }
      }
      onRowClick(data);
    };

    // 给到iView table组件的高度
    const tableHeight = ref(0);

    // 表格外层div的引用
    const gridRef: Ref<HTMLElement | null> = ref(null);

    // 表格分页组件的引用
    const girdPaginationRef: Ref<InstanceType<
      typeof AppGridPagination
    > | null> = ref(null);

    // 浏览器ResizeObserver对象
    let resizeObserver: ResizeObserver | null = null;

    // 上次监听到的表格外层div高度，一旦发生变化就重新计算
    let lastGridHeight = 0;

    // 计算表格高度（用于固定头部）
    const calcGridHeight = () => {
      // 不是嵌入视图里的表格才去算高度
      if (gridRef.value && props.modal?.mode !== 'EMBED') {
        if (c.model.source.enablePagingBar && girdPaginationRef.value) {
          const gridPage = girdPaginationRef.value.$el as HTMLElement;
          const gridPageHeight =
            gridPage.offsetHeight +
            parseFloat(window.getComputedStyle(gridPage).paddingTop);
          tableHeight.value = gridRef.value.offsetHeight - gridPageHeight;
        } else {
          tableHeight.value = gridRef.value.offsetHeight;
        }
      }
      // 如果模型配置了高度走配置的
      if (c.model.source.height > 0) {
        tableHeight.value = c.model.source.height;
      }
    };

    watch(gridRef, (newVal, oldVal) => {
      if (newVal && newVal !== oldVal) {
        calcGridHeight();
        if (window.ResizeObserver && gridRef.value) {
          resizeObserver = new ResizeObserver(entries => {
            // 处理组件高度变化
            const height = entries[0].contentRect.height;
            if (height !== lastGridHeight) {
              calcGridHeight();
              lastGridHeight = height;
            }
          });
          resizeObserver.observe(gridRef.value);
        }
      }
    });

    onUnmounted(() => {
      // 在组件销毁前取消 ResizeObserver 的观察
      if (resizeObserver) {
        resizeObserver.disconnect();
      }
    });

    const tableData = computed(() => {
      return [{ hiddenRow: true }, ...c.items];
    });

    return {
      c,
      ns,
      columns,
      tableData,
      onDbRowClick,
      onUIRowClick,
      onSelectionChange,
      onSortChange,
      onPageChange,
      onPageSizeChange,
      onPageReset,
      tableHeight,
      gridRef,
      girdPaginationRef,
    };
  },
  render() {
    if (!this.c.complete) {
      return;
    }

    // 绘制作用域插槽
    const columnSlots: IData = {};
    // 表格列自定义
    this.c.model.columns.forEach(column => {
      if (column.source.columnType === 'GROUPGRIDCOLUMN') {
        return;
      }
      const columnName = column.codeName;
      columnSlots[columnName] = ({ row, index }: IData) => {
        const rowController = this.c.rows[index - 1];
        if (row.hiddenRow) {
          return (
            <span style='word-break: break-word;white-space: pre-wrap;'>
              隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列
            </span>
          );
        }
        if (rowController) {
          return h(this.c.providers[columnName].component, {
            props: {
              controller: this.c.columns[columnName],
              row: rowController,
            },
            key: row.srfkey + columnName,
          });
        }
      };
    });

    return (
      <control-layout modelData={this.c.model}>
        <div
          ref='gridRef'
          class={[
            this.ns.b(),
            this.ns.is('show-header', !this.c.model.source.hideHeader),
            this.ns.is('enable-page', this.c.model.source.enablePagingBar),
          ]}
        >
          <i-table
            ref={'grid'}
            height={this.tableHeight}
            class={this.ns.b('content')}
            show-header={!this.c.model.source.hideHeader}
            highlight-row
            data={this.tableData}
            columns={this.columns}
            on-on-row-click={this.onUIRowClick}
            on-on-row-dblclick={this.onDbRowClick}
            on-on-selection-change={this.onSelectionChange}
            on-on-sort-change={this.onSortChange}
            row-class-name={(row: IData) => (row.hiddenRow ? 'hidden-row' : '')}
            scopedSlots={columnSlots}
          ></i-table>
          {this.c.model.source.enablePagingBar && (
            <AppGridPagination
              ref='girdPaginationRef'
              total={this.c.total}
              curPage={this.c.curPage}
              size={this.c.size}
              on-change={this.onPageChange}
              on-page-size-change={this.onPageSizeChange}
              on-page-reset={this.onPageReset}
            ></AppGridPagination>
          )}
        </div>
      </control-layout>
    );
  },
});
