import { Hot } from '@/types/components';
import { TreeNode } from '@sc/tree';
import cloneDeep from 'lodash/cloneDeep';

type GroupHeaderCell = Hot.IGroupHeaderCell | string;

interface IColumnsData {
  colHeaders: string[];
  colWidths: number[];
  columns: any[];
}

export function getColumnsSettings(columnsMeta: Hot.IColumnMeta[] | undefined): IColumnsData | null {
  if (!columnsMeta) return null;
  // 列的元数据
  const colHeaders: string[] = [];
  const colWidths: number[] = [];
  const columns: any[] = [];

  cloneDeep(columnsMeta).forEach(meta => {
    colHeaders.push(meta.title);
    colWidths.push(meta.width);
    delete (meta as any).title;
    delete (meta as any).width;
    columns.push(meta);
  });

  return {
    colHeaders,
    colWidths,
    columns,
  };
}

// 生成 nestedHeaders 配置项
export function generateNestedHeadersData(groupingHeaders: GroupHeaderCell[][]) {
  // 行的个数
  const rowNums = groupingHeaders.length;
  // 列的个数
  let colNums = 0;
  groupingHeaders[0].forEach(cell => {
    if (typeof cell === 'string') {
      colNums += 1;
    } else {
      colNums += cell.colspan || 1;
    }
  });

  // 二维数组，记录每个 th 对应的 “合并后的单元格” 的 id，初始化为 0
  const cellGrid = new Array(rowNums).fill(null).map(() => new Array(colNums).fill(0));

  // 合并后的单元格的 id，从左到右，从上到下，依次递增
  let cellID = 0;

  // 合并后的单元格的 id 具体的信息映射：当前的合并单元格的 label、起始的 th 的坐标(x、y)、rowspan、colspan
  const cellMap: Common.IStringIndex = {};

  /**
   * 下面的循环是为了填充 cellGrid 和 cellMap
   */
  // 遍历 groupingHeaders 选项中的每一行
  groupingHeaders.forEach((rowData, row) => {
    // 遍历当前行中的每一列，每次都从 col = 0 开始
    let col = 0;
    rowData.forEach(cellData => {
      let cell = cellData as Hot.IGroupHeaderCell;
      if (typeof cellData === 'string') cell = { label: cellData };
      const { label, rowspan = 1, colspan = 1 } = cell;

      // 当前的 th 已经属于某个合并后的单元格了
      if (cellGrid[row][col]) {
        // 在当前行中，从 col 列开始往后找，直至找到一个没有被合并单元格占据的 th 为止
        for (let j = col; j < colNums; j++) {
          if (!cellGrid[row][j]) {
            col = j;
            break;
          }
        }
      }
      cellID += 1;
      cellMap[cellID] = { label, x: row, y: col, rowspan, colspan };

      // 按照 rowspan 和 colspan，将当前的 th 附近的其他 th 纳入合并单元格中
      for (let i = row; i < row + rowspan; i++) cellGrid[i][col] = cellID;
      for (let j = col; j < col + colspan; j++) cellGrid[row][j] = cellID;
      col += colspan;
    });
  });

  // nestedHeaders 配置项
  const nestedHeaders: any[] = new Array(rowNums).fill(null).map(() => []);

  for (let i = 0; i < rowNums; i++) {
    for (let j = 0; j < colNums; ) {
      const { label, colspan } = cellMap[cellGrid[i][j]];
      if (colspan === 1) {
        nestedHeaders[i].push(label);
      } else {
        nestedHeaders[i].push({ label, colspan });
      }
      j += colspan;
    }
  }
  return {
    nestedHeaders,
    cellGrid,
  };
}

export function getTableData(tree: boolean, data: any[]): any[] {
  // handsontable 真正渲染的数据（如，props.tree为true时，只渲染 visible 为 true 的行）
  let tableData = [];
  // 判断是不是树
  if (tree) {
    // 针对树结构做的特殊处理（隐藏某些行）
    let i = 0;
    let rowData;
    let ctx;
    while (i < data.length) {
      rowData = data[i] as TreeNode;
      ctx = rowData.getCtx();

      tableData.push(rowData);
      // 展开
      if (ctx.expanded) {
        i += 1;
      }
      // 收缩
      else {
        // 后代节点
        i += ctx.posterity().length + 1;
      }
    }
  } else {
    tableData = data;
  }
  return tableData;
}

// props 的 readOnly 为 true 时优先级最高
export function overwriteReadOnly(tableSettings: Hot.ISettings, globalReadOnly: boolean) {
  const { cells, cell, columns } = tableSettings;
  if (cells && typeof cells === 'function') {
    tableSettings.cells = (row?: number, col?: number, prop?: any) => {
      const cellProperties = cells(row, col, prop);
      if (globalReadOnly) {
        cellProperties.readOnly = true;
      }
      return cellProperties;
    };
  }

  cell &&
    cell.forEach((item: { readOnly: boolean; }) => {
      if (globalReadOnly) {
        item.readOnly = true;
      }
    });

  if (columns && typeof columns !== 'function') {
    columns.forEach((column: { readOnly: boolean; }) => {
      if (globalReadOnly) {
        column.readOnly = true;
      }
    });
  }
}

export default function useTableSettings(props: Readonly<Hot.IHandsontableProps>): Hot.ISettings {
  const { data, tree, readOnly } = props;
  const { columnsMeta, groupingHeaders } = props.settings;
  // 列的元数据
  const columnsData = getColumnsSettings(columnsMeta);

  let nestedHeadersData;
  // 表头分组
  if (groupingHeaders) {
    nestedHeadersData = generateNestedHeadersData(groupingHeaders);
  }

  // handsontable 真正渲染的数据（如，props.tree为true时，只渲染 visible 为 true 的行）
  const tableData = getTableData(tree, data);

  if (tree) {
    // 树结构不支持 manualRowMove
    props.settings.manualRowMove = false;
  }

  const tableSettings = {
    ...props.settings,
    ...columnsData,
    ...nestedHeadersData,
    data: tableData,
    // readOnly,
  };
  delete tableSettings.columnsMeta;
  delete tableSettings.groupingHeaders;

  overwriteReadOnly(tableSettings, readOnly);

  return tableSettings;
}
