import React from 'react';

import Tree from 'rc-tree';
import { DataNode, EventDataNode } from 'rc-tree/lib/interface';
import { useNavigate } from 'react-router';
import Loading from '../../common/lib/Loading';
import { BrainAtlasType, MultiLang } from '../../config';
import Functions from '../../functions';
import IndexUtil, { INDEX_ID_PUBLIC, Index } from '../lib/IndexUtil';

import styles from './IndexTree.module.css';

interface Props {
  lang: MultiLang;
  type: BrainAtlasType;
}

const IndexTree: React.FC<Props> = (props) => {
  const { lang, type } = props;
  const navigate = useNavigate();

  const [tree, setTree] = React.useState<DataNode[]>([]);
  const [keys, setKeys] = React.useState<string[]>([]);
  const [expandedKeys, setExpandedKeys] = React.useState<string[]>([]);
  const [selectedKeys, setSelectedKeys] = React.useState<number[]>([]);

  React.useEffect(() => {
    const tree: DataNode[] = [];
    const keys: string[] = [];
    const eKeys: string[] = [];
    const makeTreeNode = (index: Index, depth: number, func: (node: DataNode) => void): void => {
      const title =
        Functions.mlang(index.title, lang) +
        (index.numOfItems > 0 ? ' (' + index.numOfItems + ')' : '');
      IndexUtil.getChildren(type, index.id, (children) => {
        if (children.length === 0) {
          func({ key: String(index.id), title: title });
        } else {
          if (depth < 1) {
            eKeys.push(String(index.id));
          }
          keys.push(String(index.id));
          const childTreeNodes: DataNode[] = [];
          let called = 0;
          children.forEach((value: Index) => {
            makeTreeNode(value, depth + 1, (cNode) => {
              called++;
              childTreeNodes.push(cNode);
              if (called === children.length) {
                func({ key: String(index.id), title: title, children: childTreeNodes });
              }
            });
          });
        }
      });
    };
    IndexUtil.get(type, INDEX_ID_PUBLIC, (index) => {
      if (index != null) {
        makeTreeNode(index, 0, (node) => {
          tree.push(node);
          setTree(tree);
          setKeys(keys);
          setExpandedKeys(eKeys);
          setSelectedKeys([]);
        });
      }
    });
  }, [lang, type]);

  const handleClickOpenAll = () => {
    setExpandedKeys(keys);
  };

  const handleClickCloseAll = () => {
    setExpandedKeys([]);
  };

  const handleExpand: (
    expandedKeys: React.Key[],
    info: {
      node: EventDataNode<DataNode>;
      expanded: boolean;
      nativeEvent: MouseEvent;
    },
  ) => void = (expandedKeys) => {
    const keys: string[] = expandedKeys.map((key) => {
      return typeof key === 'string' ? key : String(key);
    });
    setExpandedKeys(keys);
  };

  const handleSelect: (
    selectedKeys: React.Key[],
    info: {
      event: 'select';
      selected: boolean;
      node: EventDataNode<DataNode>;
      selectedNodes: DataNode[];
      nativeEvent: MouseEvent;
    },
  ) => void = (selectedKeys) => {
    const selectedKey = selectedKeys.shift() ?? 0;
    const key = typeof selectedKey === 'string' ? parseInt(selectedKey, 10) : selectedKey;
    const url = IndexUtil.getUrl(type, key);
    navigate(url);
    setSelectedKeys([]);
  };

  if (tree.length === 0) {
    return <Loading />;
  }

  return (
    <div className={styles.container}>
      <button className={styles.formButton} onClick={handleClickOpenAll}>
        open all
      </button>
      <button className={styles.formButton} onClick={handleClickCloseAll}>
        close all
      </button>
      <Tree
        className={styles.indexTree}
        expandedKeys={expandedKeys}
        selectedKeys={selectedKeys}
        onExpand={handleExpand}
        onSelect={handleSelect}
        showIcon={false}
        treeData={tree}
      />
    </div>
  );
};

export default IndexTree;
