<script lang="ts">
import { GroupingField, translateValueByKey } from '@oinone/kunlun-engine';
import { EDirection } from '@oinone/kunlun-service';
import { TableFixed } from '@oinone/kunlun-vue-ui';
import { OioIcon, ReturnPromise, StringHelper } from '@oinone/kunlun-vue-ui-antd';
import { PropRecordHelper } from '@oinone/kunlun-vue-ui-common';
import { Popover as APopover } from 'ant-design-vue';
import { createVNode, defineComponent, type PropType, ref, type VNode } from 'vue';
import { VxeTableConstructor, VxeTablePrivateMethods } from 'vxe-table';

type TableOperatorHandlerFn = (table, column) => ReturnPromise<boolean>;

const classNamePrefix = 'default-column-quick-operation';

function createOperationItem(title: string, icon: string, onClick: Function, classNames?: string | string[]) {
  const translateTitle = translateValueByKey(title);
  return createVNode(
    'div',
    {
      class: StringHelper.append([`oio-popover-select-item ${classNamePrefix}-item`], classNames),
      title: translateTitle,
      onClick
    },
    [
      createVNode(OioIcon, { icon, size: 14 }),
      createVNode('span', { class: 'oio-popover-select-item-title' }, translateTitle)
    ]
  );
}

export default defineComponent({
  name: 'DefaultQuickOperationColumn',
  components: {
    APopover
  },
  props: {
    table: {
      type: Object as PropType<VxeTableConstructor & VxeTablePrivateMethods>,
      required: true
    },
    column: {
      type: Object,
      required: true
    },
    sortable: {
      type: Boolean,
      default: undefined
    },
    enableGrouping: {
      type: Boolean,
      default: false
    },
    groupList: {
      type: Array as PropType<GroupingField[]>,
      default: () => []
    },
    onGroupChange: {
      type: Function
    },
    handleOrderByASC: {
      type: Function as PropType<TableOperatorHandlerFn>
    },
    handleOrderByDESC: {
      type: Function as PropType<TableOperatorHandlerFn>
    },
    handleClearOrder: {
      type: Function as PropType<TableOperatorHandlerFn>
    },
    handleFreezeLeft: {
      type: Function as PropType<TableOperatorHandlerFn>
    },
    handleFreezeRight: {
      type: Function as PropType<TableOperatorHandlerFn>
    },
    handleClearFreeze: {
      type: Function as PropType<TableOperatorHandlerFn>
    },
    handleClearAllFreeze: {
      type: Function as PropType<(fixed: TableFixed) => ReturnPromise<boolean>>
    },
    handleHide: {
      type: Function as PropType<TableOperatorHandlerFn>
    }
  },
  setup(props) {
    const visible = ref(false);

    const onUpdateVisible = (val: boolean) => {
      visible.value = val;
    };

    const createHandle = <R,>(
      fn: (...args: unknown[]) => ReturnPromise<R>
    ): ((...args: unknown[]) => ReturnPromise<R>) => {
      return async (...args: unknown[]) => {
        const res = await fn(...args);
        if (res == null || !!res) {
          visible.value = false;
        }
        return res;
      };
    };

    const handleOrderByASC = createHandle(() => {
      return props.handleOrderByASC?.(props.table, props.column);
    });

    const handleOrderByDESC = createHandle(() => {
      return props.handleOrderByDESC?.(props.table, props.column);
    });

    const handleClearOrder = createHandle(() => {
      return props.handleClearOrder?.(props.table, props.column);
    });

    const handleFreezeLeft = createHandle(() => {
      return props.handleFreezeLeft?.(props.table, props.column);
    });

    const handleFreezeRight = createHandle(() => {
      return props.handleFreezeRight?.(props.table, props.column);
    });

    const handleClearFreeze = createHandle(() => {
      return props.handleClearFreeze?.(props.table, props.column);
    });

    const handleClearAllFreeze = createHandle(() => {
      return props.handleClearAllFreeze?.(TableFixed.all);
    });

    const handleHide = createHandle(() => {
      return props.handleHide?.(props.table, props.column);
    });

    return {
      visible,
      onUpdateVisible,

      handleOrderByASC,
      handleOrderByDESC,
      handleClearOrder,
      handleFreezeLeft,
      handleFreezeRight,
      handleClearFreeze,
      handleClearAllFreeze,
      handleHide
    };
  },
  render() {
    const {
      $slots,

      column,
      sortable,
      enableGrouping,
      groupList,

      visible,
      onUpdateVisible,

      handleOrderByASC,
      handleOrderByDESC,
      handleClearOrder,
      handleFreezeLeft,
      handleFreezeRight,
      handleClearFreeze,
      handleClearAllFreeze,
      handleHide,
      onGroupChange
    } = this;
    const { trigger: triggerSlot } = PropRecordHelper.collectionSlots($slots, ['trigger']);
    let triggerChildren: VNode[];
    if (triggerSlot) {
      triggerChildren = triggerSlot();
    } else {
      triggerChildren = [
        createVNode(OioIcon, {
          icon: 'oinone-gengduo11',
          size: 16
        })
      ];
    }

    const popover = createVNode(
      APopover,
      {
        visible,
        overlayClassName: `oio-popover oio-popover-select-panel ${classNamePrefix}-overlay`,
        placement: 'bottomRight',
        'onUpdate:visible': onUpdateVisible
      },
      {
        default: () => triggerChildren,
        content: () => {
          const { fixed, order, field } = column;
          const options: VNode[] = [];
          if (sortable) {
            if (order === 'asc') {
              options.push(
                createOperationItem('取消排序', 'oinone-quxiaopaixu', handleClearOrder),
                createOperationItem('降序', 'oinone-jiangxu', handleOrderByDESC)
              );
            } else if (order === 'desc') {
              options.push(
                createOperationItem('升序', 'oinone-shengxu', handleOrderByASC),
                createOperationItem('取消排序', 'oinone-quxiaopaixu', handleClearOrder)
              );
            } else {
              options.push(
                createOperationItem('升序', 'oinone-shengxu', handleOrderByASC),
                createOperationItem('降序', 'oinone-jiangxu', handleOrderByDESC)
              );
            }
          }
          if (fixed) {
            options.push(createOperationItem('取消冻结', 'oinone-quxiaodongjie', handleClearFreeze));
            options.push(createOperationItem('取消全部冻结', 'oinone-quxiaodongjie', handleClearAllFreeze));
          } else {
            options.push(
              createOperationItem('冻结左侧至此列', 'oinone-dongjiezuoce', handleFreezeLeft),
              createOperationItem('冻结右侧至此列', 'oinone-dongjieyouce', handleFreezeRight)
            );
          }
          options.push(createOperationItem('隐藏此列', 'oinone-yincangcilie', handleHide));

          if (enableGrouping) {
            if (groupList?.length && groupList.some((item) => item.field === field)) {
              options.push(
                createOperationItem('取消分组', 'oinone-ungroup-outlined', () => {
                  const list = groupList || [];
                  const index = list?.findIndex((item) => item.field === field);
                  list.splice(index, 1);
                  onGroupChange?.(list);
                })
              );
            } else {
              options.push(
                createOperationItem('以此字段分组', 'oinone-group-outlined', () => {
                  const list = groupList || [];
                  list.push({ field, direction: EDirection.ASC });
                  onGroupChange?.(list);
                })
              );
            }
          }
          return options;
        }
      }
    );
    return createVNode('span', { class: classNamePrefix }, [popover]);
  }
});
</script>
<style lang="scss">
.default-column-quick-operation {
  .oio-icon.oio-icon-oinone-gengduo11 {
    color: var(--oio-table-title-color);
    cursor: pointer;
  }
}

.default-column-quick-operation-overlay {
  .ant-popover-arrow {
    display: none;
  }
}
</style>
