import { useState } from "react";
import { Group } from "@visx/group";
import { hierarchy, Tree } from "@visx/hierarchy";
import { LinearGradient } from "@visx/gradient";
import { RenderSVGWithUISchemaElement } from "./RenderSVGWithUISchemaElememts";
import Legend from "./Legend";
import _ from "lodash";
import getLinkComponent from "./TreeHelperComponents";
import { TreeMapProps } from "./interface";
const defaultMargin = { top: 70, left: 70, right: 70, bottom: 70 };
export const ComponentType = {
  component: "component",
};
export default function TreeMap(props: TreeMapProps) {
  const {
    uischema,
    treeData,
    setTreeData,

    width: totalWidth,
    height: totalHeight,
    dimension,
    margin = defaultMargin,
  } = props;

  const UiSchemaData: any = uischema.config.main;
  const [colorHolder, setColorHolder] = useState<Record<string, string>>({});
  const [, setRefresh] = useState<boolean>(false);
  const innerWidth = totalWidth - margin.left - margin.right;
  const innerHeight = totalHeight - margin.top - margin.bottom;
  let origin: { x: number; y: number };
  let sizeWidth: number;
  let sizeHeight: number;
  if (UiSchemaData.layout === "polar") {
    origin = {
      x: innerWidth / 2,
      y: innerHeight / 2,
    };
    sizeWidth = 2 * Math.PI;
    sizeHeight = Math.min(innerWidth, innerHeight) / 2;
  } else {
    origin = { x: 0, y: 0 };
    if (dimension.orientation === "vertical") {
      sizeWidth = innerWidth;
      sizeHeight = innerHeight;
    } else {
      sizeWidth = innerHeight;
      sizeHeight = innerWidth;
    }
  }
  const LinkComponent = getLinkComponent({
    layout: UiSchemaData.layout,
    linkType: UiSchemaData.linkType,
    orientation: dimension.orientation,
  });
  return totalWidth < 10 ? null : (
    <div style={{ position: "relative" }}>
      <div
        style={{
          position: "absolute",
          top: 2,
          left: 2,
          background: UiSchemaData?.background || "#ffffff",
          width: "300px",
          borderRadius: "10px 0 0 0",
        }}
      >
        <Legend
          dataKeyArray={Object.keys(colorHolder)}
          colorRange={Object.values(colorHolder)}
        />
      </div>
      <svg width={totalWidth} height={totalHeight}>
        <LinearGradient id="links-gradient" from="#5e6ef2" to="#5e6ef2" />
        <rect
          width={totalWidth}
          height={totalHeight}
          rx={dimension.muliplier > 1 ? 0 : 14}
          fill={UiSchemaData?.background || "#ffffff"}
        />
        <Group top={margin.top} left={margin.left}>
          <Tree
            root={generateTreeWithIndexPaths(treeData||{})}
            size={[sizeWidth, sizeHeight]}
            separation={(a, b) => (a.parent === b.parent ? 1 : 0.5) / a.depth}
          >
            {(tree) => (
              <Group top={origin.y} left={origin.x}>
                {tree.links().map((link, i) => (
                  <LinkComponent
                    key={i}
                    defaultMargin
                    data={link}
                    percent={1}
                    stroke="rgb(254,110,158,0.6)"
                    strokeWidth="1"
                    fill="none"
                  />
                ))}

                {tree.descendants().map((node, key) => {
                  const width = dimension.width;
                  const height = dimension.height;

                  let top: number;
                  let left: number;
                  if (dimension.orientation === "vertical") {
                    top = node.y;
                    left = node.x;
                  } else {
                    top = node.x;
                    left = node.y;
                  }
                  return (
                    <Group
                      onClick={() => {
                        node.data.isExpanded = !node.data.isExpanded;
                        setRefresh((pre) => !pre);
                      }}
                      style={{ padding: "20px", border: "2px solid white" }}
                      top={top}
                      left={left}
                      key={node.data.id}
                    >
                      <RenderSVGWithUISchemaElement
                        key={key}
                        {...props}
                        colorHolder={colorHolder}
                        x={-width / 2}
                        y={-height / 2}
                        width={width}
                        height={height}
                        node={node}
                        setData={setTreeData}
                        setColorHolder={setColorHolder}
                      />
                    </Group>
                  );
                })}
              </Group>
            )}
          </Tree>
        </Group>
      </svg>
    </div>
  );
}

function generateTreeWithIndexPaths(rootNode) {
  return hierarchy(rootNode, (d: any) =>
    d.isExpanded ? null : d.children
  ).each((node) => {
    const indexPath = node
      .ancestors()
      .map((ancestor) => {
        return ancestor.parent ? ancestor.parent.children.indexOf(ancestor) : 0;
      })
      .reverse()
      .join(".children.");
    node.data.path = indexPath;
  });
}
