<template>
  <div
    class="handsontable-container"
    :style="borderStyle"
    v-loading="loading"
    element-loading-background="rgba(245, 245, 245, 0.5)"
  >
    <div class="table-wrapper" ref="handsontableRef"></div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue';
import Handsontable from '@sc/handsontable';
import { TreeNode } from '@sc/tree';
import debounce from 'lodash/debounce';
import { off } from '@/utils/frontend/dom';
import useClickPosition from './composables/useClickPosition';
import useInstance from './composables/useInstance';
import useTableSettings, { getColumnsSettings, getTableData, overwriteReadOnly } from './composables/useTableSettings';
import './renderer/registerRenderers';
import { Hot } from '@/types/components';
// import './cell-types/registerCellTypes';

export default defineComponent({
  name: 'Handsontable',
  props: {
    // 表格的数据
    data: {
      type: Array,
      required: true,
    },
    // 表格的设置选项
    settings: {
      type: Object,
      required: true,
    },
    // 是否是树结构，即每行数据是否是 `TreeNode`
    tree: {
      type: Boolean,
      default: false,
    },
    // 边框, none 表示没有边框
    border: {
      type: String,
      default: 'top,right,bottom,left',
    },
    // 整个表格是否只读
    readOnly: {
      type: Boolean,
      default: false,
    },
    // 是否处于 loading 状态
    loading: {
      type: Boolean,
      default: false,
    },
  },
  setup(props) {
    // 模板引用
    const handsontableRef = ref<HTMLElement | null>(null);

    const hotProps = props as Hot.IHandsontableProps;
    const tableSettings = useTableSettings(hotProps);

    let rawData = props.data as any;

    // Handsontable 实例
    let instance: Handsontable | null;

    type RowHeaders = boolean | ((visualRow: number) => number);
    const getRowHeader = (): RowHeaders => {
      if (tableSettings.rowHeaders !== undefined) return tableSettings.rowHeaders as any;
      return props.tree
        ? (visualRow: number) => {
          if (instance) {
            const rowSourceData = instance.getSourceDataAtRow(instance.toPhysicalRow(visualRow)) as TreeNode;
            return rowSourceData.getCtx().row() + 1;
          }
          return visualRow;
        }
        : true;
    };
    // 重新渲染，供外界调用
    const Render = () => instance && instance.render();

    const onResize = debounce(() => Render(), 100);

    // 监听 mousedownPosition 事件的处理器
    let clickPositionHandler: any;

    onMounted(() => {
      const wrapperDOM = handsontableRef.value as HTMLElement;
      // handsontable 实例
      instance = useInstance(wrapperDOM, tableSettings);

      // 获取鼠标点击的区域相关代码
      clickPositionHandler = useClickPosition(wrapperDOM, tableSettings);

      // 设置行号
      (() => {
        const rowHeaders = getRowHeader();
        instance.updateSettings({ rowHeaders }, false);
      })();

      // 改变窗口大小监听事件
      window.addEventListener('resize', onResize);
    });

    const { readOnly, tree } = toRefs(props);

    // 重新加载数据，供外界调用
    const Load = (data?: any) => {
      if (data) rawData = data;
      instance && instance.loadData(getTableData(tree.value, rawData));
    };

    // 获取 instance，供外界调用
    const GetInstance = () => instance;

    // 更新 Settings，供外界调用（如增加或减少列）
    const Update = (newTableSettings: Hot.ISettings) => {
      const { columnsMeta } = newTableSettings;
      const columnsData = getColumnsSettings(columnsMeta);
      let newSettings;
      if (columnsData) {
        newSettings = { ...columnsData, ...newTableSettings };
        delete newSettings.columnsMeta;
      } else {
        newSettings = newTableSettings;
      }

      overwriteReadOnly(newSettings, readOnly.value);

      if (newSettings.rowHeaders === undefined)
        // 设置行号
        newSettings.rowHeaders = getRowHeader();
      instance && instance.updateSettings(newSettings, false);
    };

    watch(readOnly, () => {
      Update(props.settings);
    });
    watch(tree, () => {
      const newSettings = props.settings;
      const { columnsMeta } = newSettings;
      columnsMeta &&
        columnsMeta.forEach((columnMeta: any) => {
          if (columnMeta.renderer === 'wc.switcherRenderer') {
            delete columnMeta.renderer;
          }
        });

      Update(newSettings);
      Load();
    });
    // 组件 unmount 之前销毁 handsontable 实例
    onBeforeUnmount(() => {
      if (instance) {
        window.removeEventListener('resize', onResize);

        // 移除所有的监听器
        // Handsontable.hooks.destroy && Handsontable.hooks.destroy(instance);
        instance.destroy();
        instance = null;
      }
      if (clickPositionHandler) off(document.body, 'mouseup', clickPositionHandler);
    });

    // 边框样式
    const borderStyle = computed(() => {
      if (props.border === 'none') {
        return {
          border: 'none',
        };
      }
      const borders = props.border.split(',');
      const style = {} as any;
      borders.forEach(border => {
        style[`border-${border}`] = '1px solid #d4d4d4';
      });
      return style;
    });

    return {
      handsontableRef,
      borderStyle,
      Render,
      Update,
      Load,
      GetInstance,
    };
  },
});
</script>

<style lang="scss" scoped>
.handsontable-container {
  position: relative;
  width: 100%;
  height: 100%;
  @include scrollbar-handsontable;
}

.table-wrapper {
  width: 100%;
  height: 100%;
  overflow: hidden;

  /* ::v-deep > .ht_master {
  } */

  ::v-deep > .ht_clone_top_left_corner,
  ::v-deep > .ht_clone_top {
    .htCore {
      .real-th {
        position: relative;
        overflow: visible;

        &.ht__highlight {
          .relative {
            background-color: #dad8d6 !important;
          }
        }

        .relative {
          position: absolute;
          bottom: 0;
          left: 0;
          padding: 0;
          width: 100%;
          background-color: $smoke;

          &:hover {
            background-color: #dfdfdf !important;
          }
        }
      }
    }
  }

  /* ::v-deep > .ht_clone_bottom {
  } */

  ::v-deep > .ht_clone_left {
    // overflow: visible !important;

    .wtHolder {
      width: 100% !important;
    }

    .htCore {
      transition: box-shadow 0.3s ease;

      &.shadow {
        box-shadow: 4px 0 4px -3px rgba(0, 0, 0, 0.2);
      }

      /* tbody {
        // 这段代码会导致小屏幕上缩放分辨率时，表格行错位的问题
        th {
          display: flex;
          align-items: center;
          justify-content: center;
        }
      } */
    }
  }

  ::v-deep > .ht_clone_top_left_corner {
    .htCore {
      thead {
        tr {
          th {
            border-color: $gainsboro;
          }
        }
      }
    }
  }

  /*  ::v-deep > .handsontableInputHolder {
  }
 */
  ::v-deep > .ht_master,
  ::v-deep > .ht_clone_top,
  ::v-deep > .ht_clone_bottom,
  ::v-deep > .ht_clone_left,
  ::v-deep > .ht_clone_top_left_corner,
  ::v-deep > .handsontableInputHolder {
    .htCore {
      td,
      th {
        // 当前选中行的样式
        &.current-row {
          background-color: $light-sky-blue !important;
        }
        &.show-highlight {
          background-color: #c1e1fc !important;
        }
        // 当前选中单元格的样式
        &.current {
          &.highlight {
            background-color: #c1e1fc !important;

            .custom-button {
              display: inline !important;
              vertical-align: middle;
              margin: -1px 0 0 2px;
            }
          }
        }
      }

      th {
        border-color: $gainsboro !important;
        background-color: $smoke !important;
        color: $black;
        cursor: pointer;

        &:hover {
          background-color: #dfdfdf !important;
        }

        &.ht__highlight {
          background-color: #dad8d6 !important;

          .colHeader,
          .rowHeader {
            font-weight: bold;
            color: #2577c2;
          }
        }
      }

      tbody {
        tr {
          &.hover {
            td {
              background-color: $ghost-grey;
            }
          }

          td {
            transition: background-color 0.15s;
            border-color: $gainsboro;
            color: $black;

            &.bg-danger {
              background-color: #fbe3e3;
            }

            &.font-danger {
              color: $danger;
            }

            &.wcSingleLine {
              white-space: nowrap;
            }

            &.htMiddle {
              vertical-align: middle;
            }
          }
        }
      }
    }

    .htBorders {
      .wtBorder.corner {
        cursor: cell;
      }
    }
  }

  // 没有左边框
  ::v-deep > .ht_clone_left {
    .htCore {
      th {
        border-left: none;
      }
    }
  }

  ::v-deep > .ht_clone_top_left_corner {
    .htCore {
      thead {
        th:first-child {
          border-left: none;
        }
      }
    }
  }

  // 没有上边框
  ::v-deep > .ht_master,
  ::v-deep > .ht_clone_top,
  ::v-deep > .ht_clone_bottom,
  ::v-deep > .ht_clone_left,
  ::v-deep > .ht_clone_top_left_corner,
  ::v-deep > .handsontableInputHolder {
    .htCore {
      thead {
        tr {
          th {
            border-top: none !important;
          }
        }
      }
      /*tbody {
        tr {
          td {
            border-left: none !important;
          }
        }
      }*/
    }
  }

  ::v-deep .red {
    color: red !important;
  }

  ::v-deep .green {
    color: green !important;
  }
  ::v-deep .stateCheckBox::after {
    content: "";
    display: block;
    width: 7px;
    height: 7px;
    background-color: #007bff;
    transform: translate(3px, 3px);
  }

  // 调整列大小的手柄
  ::v-deep .manualColumnResizer {
    cursor: ew-resize;
    transform: translateX(3px);
  }

  // 调整行大小的手柄
  ::v-deep .manualRowResizer {
    cursor: ns-resize;
    transform: translateY(3px);
  }
}
</style>
