import { Renderable } from '../../core/renderable.js';
import { Summary } from '../../component/components/summary.js';

const filterHeadings = (list, depths = [2]) => {
  if (!list || list.length === 0) return undefined;
  let heading = list[0];
  if (!depths.includes(heading.depth)) return undefined;
  for (heading of list) {
    if (Array.isArray(heading.list)) {
      heading.list = filterHeadings(heading.list, depths);
    }
  }
  return list;
}

class TOC extends Renderable {
  constructor (data, nodes) {
    super(data);
    this._hasToc = data.toc !== undefined;
    this._nodes = nodes;
  }

  async render () {
    if (!this._hasToc) {
      return '';
    }

    const headings = this._nodes.filter(node => node.type === 'heading').map (heading => {
      return {
        depth: heading.depth,
        href: `#${heading.normalizedId}`,
        label: heading.text,
      };
    });

    let depths = headings.map(heading => heading.depth).filter((depth, index, array) => array.indexOf(depth) === index).sort((a, b) => a - b);

    let depth = depths[0];
    const lists = [];
    let mainList = [];
    let list = mainList;
    let previous;

    for (const heading of headings) {
      switch (true) {
        case heading.depth === depth:
          list.push(heading);
          break;

        case heading.depth < depth:
          while (lists.length > 0 && list[0].depth > heading.depth) {
            list = lists.pop();
          }
          if (list[0].depth === heading.depth) {
            list.push(heading);
            depth = heading.depth;
          }
          else {
            list = [heading];
            lists.push(list);
            if (previous) previous.list = list;
            depth = heading.depth;
          }
          break;

        case heading.depth > depth:
          lists.push(list);
          list = [heading];
          if (previous) previous.list = list;
          depth = heading.depth;
          break;
      }

      previous = heading;
    }

    while (mainList?.length === 1) mainList = mainList[0].list;

    if (!mainList || mainList?.length === 0) return '';

    switch (typeof this._data.toc) {
      case 'string':
        depths = this._data.toc.split(',').map(depth => parseInt(depth.trim(), 10)).filter(depth => !isNaN(depth));
        mainList = filterHeadings(mainList, depths);
        break;
      case 'number':
        mainList = filterHeadings(mainList, [this._data.toc]);
        break;
    }

    const summary = new Summary({ title: this.data?.fragments?.summary?.title, list: mainList });

    return `<div class="fr-mb-6v" >
    ${await summary.render()}
    </div>`;
  }
}

export { TOC };
