import Handsontable, { GridSettings } from '@sc/handsontable';
import { parse, query, on, queryAll } from '@/utils/frontend/dom';
import { TreeNode } from '@sc/tree';

interface IIconItem {
  icon: string;
  color?: string;
  callback?: () => void;
}

interface ICellProperties extends GridSettings {
  // 最前面的 icons
  headIcons?: IIconItem[];
  // 文本前面的 icons
  textIcons?: IIconItem[];
  // 直接跟在文本后面的 icons
  textBehindIcons?: IIconItem[];
  // 在单元格最后面的 icons
  tailIcons?: IIconItem[];
  // 最前面的偏置距离，默认是 5
  offsetLeft?: number;
}

/* 此 renderer 仅适用于树结构的表格 */
export default function (
  instance: Handsontable,
  row: number,
  col: number,
  prop: string | number,
  value: any,
  cellProperties: ICellProperties
): HTMLElement {
  const { headIcons = [], textIcons = [], textBehindIcons = [], tailIcons = [], offsetLeft = 5 } = cellProperties;

  // 当前行的源数据
  const rowSourceData = instance.getSourceDataAtRow(row) as TreeNode;
  // 当前行的上下文对象
  const ctx = rowSourceData.getCtx();
  const level = ctx.depth();
  const isLastChild = !ctx.next();
  const isFirstAncestor = !ctx.parent() && !ctx.prev();
  const isSingleNode = isLastChild && isFirstAncestor && !ctx.firstChild();

  const toggleIconCls = (() => {
    if (ctx.children().length) return ctx.expanded ? 'ht-toggle-icon-shrink' : 'ht-toggle-icon-expand';
    return '';
  })();

  let headIconHtml = '';
  headIcons.forEach(
    item => (headIconHtml += `<i class="iconfont ${item.icon}" style="color: ${item.color || '#007bff'}"></i>`)
  );

  let textIconHtml = '';
  textIcons.forEach(
    item => (textIconHtml += `<i class="iconfont ${item.icon}" style="color: ${item.color || '#007bff'}"></i>`)
  );

  let textBehindIconHtml = '';
  textBehindIcons.forEach(
    item =>
      (textBehindIconHtml += `<i class="iconfont ${item.icon}" style="color: ${item.color || '#007bff'}"></i>`)
  );

  let tailIconHtml = '';
  tailIcons.forEach(
    item => (tailIconHtml += `<i class="iconfont ${item.icon}" style="color: ${item.color || '#007bff'}"></i>`)
  );

  // html 模板
  const template = `
    <div class="ht-switcher-container">
        <div class="ht-switcher-wrap">
          ${headIcons.length > 0 ? `<div class="head-icon-wrap">${headIconHtml}</div>` : ''}
          <div class="tree-line-wrap">
            ${'<i class="tree-line"></i>'.repeat(level)}
          </div>
          <div class="toggle-icon-wrap">
            ${isFirstAncestor ? '' : '<i class="toggle-icon-top-line"></i>'}
            ${isSingleNode ? '' : '<i class="toggle-icon-right-line"></i>'}
            ${isLastChild ? '' : '<i class="toggle-icon-bottom-line"></i>'}
            <!-- 展开 / 收起的 icon -->
            <i class="toggle-icon ${toggleIconCls}"></i>
          </div>
          <!-- 文本 -->
          <div class="text">
            ${textIcons.length > 0 ? `<span class="text-icon-wrap">${textIconHtml}</span>` : ''}
            <span class="content">${value || ''}</span>
            ${textBehindIcons.length > 0 ? `<span class="text-behind-icon-wrap">${textBehindIconHtml}</span>` : ''}
          </div>
          ${tailIcons.length > 0 ? `<div class="tail-icon-wrap">${tailIconHtml}</div>` : ''}
        </div>
    </div>
  `;

  // 将字符串模板解析成 dom,  .switcher-container
  const container = parse(template) as HTMLElement;
  // 内部 wrap， .switcher-wrap
  const wrapper = query(container, '.ht-switcher-wrap') as HTMLElement;
  // 文本 dom
  const textContent = query(wrapper, '.text .content') as HTMLElement;
  wrapper.style.minWidth = `${
    offsetLeft +
    46 +
    17 * level +
    textIcons.length * 16 +
    textContent.innerText.length * 15 +
    textBehindIcons.length * 16
  }px`;
  // 偏置
  wrapper.style.marginLeft = `${offsetLeft}px`;

  // 展开 / 收起的 icon
  const toggleIcon = query(wrapper, '.toggle-icon') as HTMLElement;
  const tailWrap = query(wrapper, '.tail-icon-wrap') as HTMLElement;
  if (tailWrap) {
    const icons = queryAll(tailWrap, '.iconfont');
    for (let i = 0; i < icons.length; i++) {
      const icon = icons[i] as HTMLElement;
      const cb = tailIcons[i].callback;
      if (cb) {
        icon.onclick = cb;
      }
    }
  }

  const treeLines = queryAll(wrapper, '.tree-line');
  let lastIndex = 1;
  let parent = ctx.parent();
  while (parent) {
    // 父节点是否是其同级节点中的最后的子节点
    const parentIsLastChild = !parent.getCtx().next();
    if (parentIsLastChild) {
      const lastIndexTreeLine = treeLines[level - lastIndex] as HTMLElement;
      lastIndexTreeLine.style.opacity = '0';
    }
    lastIndex += 1;
    parent = parent.getCtx().parent();
  }

  // 绑定点击事件
  on(toggleIcon, 'click', () => {
    ctx.expanded = !ctx.expanded;
    const descendants = ctx.posterity();

    // 当前表格展示的源数据
    const currentSourceData = instance.getSourceData() as TreeNode[];
    // 当前行的索引
    const currentRowIndex = currentSourceData.findIndex(item => ctx.ref.ID === item.ID);

    // 展开
    if (ctx.expanded) {
      const tobeAddData = [] as TreeNode[];
      descendants.forEach(item => {
        if (item.getCtx().visible()) {
          tobeAddData.push(item);
        }
      });

      currentSourceData.splice(currentRowIndex + 1, 0, ...tobeAddData);
    }
    // 收起
    else {
      // 先将expanded设为true是为了方便获取后代节点的可见性
      ctx.expanded = true;
      let deleteCount = 0;
      descendants.forEach(item => {
        if (item.getCtx().visible()) {
          deleteCount += 1;
        }
      });
      currentSourceData.splice(currentRowIndex + 1, deleteCount);
      // 最后将expanded恢复为false
      ctx.expanded = false;
    }
    instance.loadData(currentSourceData);
  });

  return container;
}
