import React, { ReactNode, useState } from "react";
import styles from "./OrgAst.module.css";
import { Fragment } from 'react';

const OrgAst = (props: {
  setHighlight: Function;
  clearHighlights: Function;
  astTree: any,
  value: string;
}) => {
  const [selectedNode, setSelectedNode] = useState<string>("");

  function selectNode(uid: string, start: number, end: number) {
    props.setHighlight(start, end);
    setSelectedNode(uid);
  }

  if (props.astTree.status !== "success") {
    return <div className={styles.OrgAst}>Error! {props.astTree.content}</div>;
  } else {
    return (
      <div className={styles.OrgAst}>
        <OrgAstNode
          key="^"
          uid="^"
          selectNode={selectNode}
          node={props.astTree.content}
          selectedNode={selectedNode}
        />
      </div>
    );
  }
};

const OrgAstNode = (props: {
  selectNode: Function;
  node: any;
  uid: string;
  selectedNode: string;
}) => {
  function selectNode() {
    props.selectNode(
      props.uid,
      props.node["standard-properties"]["begin"] - 1,
      props.node["standard-properties"]["end"] - 1,
    );
  }

  const nodeClassName =
    props.selectedNode === props.uid
      ? styles.OrgAstNode + " " + styles.selected
      : styles.OrgAstNode;

  return (
    <div className={nodeClassName}>
      <div className={styles.OrgAstNodeType} onClick={selectNode}>
        {props.node["ast-node"]}
      </div>
      <details>
        <summary>Standard Properties</summary>
        <dl>
          <dt>begin</dt>
          <dd>{props.node["standard-properties"]["begin"]}</dd>
          <dt>contents-begin</dt>
          <dd>{props.node["standard-properties"]["contents-begin"]}</dd>
          <dt>contents-end</dt>
          <dd>{props.node["standard-properties"]["contents-end"]}</dd>
          <dt>end</dt>
          <dd>{props.node["standard-properties"]["end"]}</dd>
          <dt>post-blank</dt>
          <dd>{props.node["standard-properties"]["post-blank"]}</dd>
        </dl>
      </details>
      {!!Object.keys(props.node.properties).length ? (
        <>
          <details>
            <summary>Properties</summary>
            <OrgPropertiesList selectNode={props.selectNode}
              parentUniqueId={props.uid}
              selectedNode={props.selectedNode}
              properties={props.node.properties}
            />
          </details>
        </>
      ) : null }
      {Array.isArray(props.node.children) && props.node.children.length > 0 ? (
        <details open={true}>
          <summary>Children</summary>
          <div className={styles.OrgAstChildren}>
            <OrgAstNodeList
              selectNode={props.selectNode}
              parentUniqueId={props.uid}
              selectedNode={props.selectedNode}
              node_list={props.node.children}
            />
          </div>
        </details>
      ) : null}
    </div>
  );
};

const OrgAstNodeList = (props: {
  selectNode: Function;
  parentUniqueId: string;
  selectedNode: string;
  node_list: any[];
}): React.JSX.Element[] => {
  return props.node_list.map((node) => {
  const uid =
    props.parentUniqueId +
    "_" +
    node["ast-node"] +
    "/" +
    node["standard-properties"]["begin"] +
    "/" +
    node["standard-properties"]["end"] +
    "#";
    return (
      <OrgAstNode
        key={uid}
        uid={uid}
        selectNode={props.selectNode}
        selectedNode={props.selectedNode}
        node={node}
      />
    );
  });
};

const OrgPropertiesList = (props: {
  selectNode: Function;
  parentUniqueId: string;
  selectedNode: string;
  properties: Object;
}): React.JSX.Element => {
  const entries = Object.entries(props.properties).map(([key, value]) => {
    return (
      <Fragment key={key}>
        <dt>{key}</dt>
        <dd>{JSON.stringify(value)}</dd>
      </Fragment>
    );
  });
  return (
    <dl>
      {entries}
    </dl>
  );
};

export default OrgAst;
