import { useMemo } from "react";
import type { NavigationNode } from "@shared/types";
import { NavigationNodeType } from "@shared/types";
import { sortNavigationNodes } from "@shared/utils/collections";
import type Collection from "~/models/Collection";
import useStores from "~/hooks/useStores";

/**
 * React hook that modifies the document structure
 * of all collections present in store. Adds extra attributes
 * like type, depth and parent to each of the nodes in document
 * structure.
 *
 * @return {NavigationNode[]} collectionTrees root collection nodes of modified trees
 */
export default function useCollectionTrees(): NavigationNode[] {
  const { collections } = useStores();

  const getCollectionTree = (collection: Collection): NavigationNode => {
    const addType = (node: NavigationNode): NavigationNode => {
      if (node.children.length > 0) {
        node.children = node.children.map(addType);
      }

      node.type = node.type ? node.type : NavigationNodeType.Document;
      return node;
    };

    const addParent = (
      node: NavigationNode,
      parent: NavigationNode | null = null
    ): NavigationNode => {
      if (node.children.length > 0) {
        node.children = node.children.map((child) => addParent(child, node));
      }

      node.parent = parent;
      return node;
    };

    const addDepth = (node: NavigationNode, depth = 0): NavigationNode => {
      if (node.children.length > 0) {
        node.children = node.children.map((child) =>
          addDepth(child, depth + 1)
        );
      }

      node.depth = depth;
      return node;
    };

    const addCollectionId = (
      node: NavigationNode,
      collectionId = collection.id
    ): NavigationNode => {
      if (node.children.length > 0) {
        node.children = node.children.map((child) =>
          addCollectionId(child, collectionId)
        );
      }

      node.collectionId = collectionId;
      return node;
    };

    const collectionNode: NavigationNode = {
      id: collection.id,
      title: collection.name,
      url: collection.path,
      type: NavigationNodeType.Collection,
      children: collection.documents
        ? sortNavigationNodes(collection.documents, collection.sort, true)
        : [],
      parent: null,
    };

    return addParent(addCollectionId(addDepth(addType(collectionNode), 1)));
  };

  const key = collections.orderedData.map((o) => o.documents?.length).join("-");
  const collectionTrees = useMemo(
    () => collections.orderedData.map(getCollectionTree),
    // oxlint-disable-next-line react-hooks/exhaustive-deps
    [collections.orderedData, key]
  );

  return collectionTrees;
}
