import { useEffect, useRef, useState } from "react";
import Cytoscape from "cytoscape";
import CytoscapeComponent from "react-cytoscapejs";
import popper from "cytoscape-popper";
import { useCurrentQuiz } from "@root/quizes/hooks";

import { useQuestionsStore } from "@root/questions/store";
import { clearDragQuestionId } from "@root/questions/actions";

import { storeToNodes } from "./helper";

import "./styles.css";

import type {
  Stylesheet,
  Core,
  NodeSingular,
  AbstractEventObject,
  ElementDefinition,
} from "cytoscape";
import { QuestionsList } from "../BranchingPanel/QuestionsList";

type PopperItem = {
  id: () => string;
};

type Modifier = {
  name: string;
  options: unknown;
};

type PopperConfig = {
  popper: {
    placement: string;
    modifiers?: Modifier[];
  };
  content: (items: PopperItem[]) => void;
};

type Popper = {
  update: () => Promise<void>;
  setOptions: (modifiers: { modifiers?: Modifier[] }) => void;
};

type NodeSingularWithPopper = NodeSingular & {
  popper: (config: PopperConfig) => Popper;
};

const stylesheet: Stylesheet[] = [
  {
    selector: "node",
    style: {
      shape: "round-rectangle",
      width: 130,
      height: 130,
      backgroundColor: "#FFFFFF",
      label: "data(label)",
      "font-size": "16",
      color: "#4D4D4D",
      "text-halign": "center",
      "text-valign": "center",
      "text-wrap": "wrap",
      "text-max-width": "80",
    },
  },
  {
    selector: ".multiline-auto",
    style: {
      "text-wrap": "wrap",
      "text-max-width": "80",
    },
  },
  {
    selector: "edge",
    style: {
      width: 30,
      "line-color": "#DEDFE7",
      "curve-style": "taxi",
      "taxi-direction": "horizontal",
      "taxi-turn": 60,
    },
  },
  {
    selector: ":selected",
    style: {
      "border-style": "solid",
      "border-width": 1.5,
      "border-color": "#9A9AAF",
    },
  },
];

Cytoscape.use(popper);

export const CsComponent = () => {
  const quiz = useCurrentQuiz();

  const { dragQuestionId, questions } = useQuestionsStore()
  const [startCreate, setStartCreate] = useState("");
  const [startRemove, setStartRemove] = useState("");

  const cyRef = useRef<Core | null>(null);
  const plusesContainer = useRef<HTMLDivElement | null>(null);
  const crossesContainer = useRef<HTMLDivElement | null>(null);
  const gearsContainer = useRef<HTMLDivElement | null>(null);

  const addNode = ({ parentNodeId }: { parentNodeId: string }) => {
    const cy = cyRef?.current

    //Если детей больше 1 - предупреждаем стор вопросов об открытии модалки ветвления
    // if (Object.keys(currentNode.children).length > 1) {
    //   setOpenedModalSettings(question.index)
    // } else {
    // //Если ребёнок первый - добавляем его родителю как дефолтный
    //   parentQuestion.question.content.rule.default = Object.keys(newNode)[0].split("_").pop()
    //   updateQuestionsList(quiz, parentQuestion.index, parentQuestion.question);
    // }


    console.log(dragQuestionId)
    // cy?.add({

    // })
  }

  useEffect(() => {
    if (startCreate) {
      addNode({ parentNodeId: startCreate });
      clearDragQuestionId()
      setStartCreate("");
    }
  }, [startCreate]);

  useEffect(() => {
    if (startRemove) {
      // removeNode(quiz, startRemove);
      setStartRemove("");
    }
  }, [startRemove]);

  useEffect(() => {
    document.querySelector("#root")?.addEventListener("mouseup", clearDragQuestionId);
    const cy = cyRef.current;
     //cy?.add(storeToNodes(questions))
    cy?.add(
      [
        {
          "data": {
            "id": "1",
            "label": "2"
          }
        },
        {
          "data": {
            "id": "1 2",
            "label": "Вы идёте в школу"
          }
        },
        {
          "data": {
            "id": "1 3",
            "label": "1"
          }
        },
        {
          "data": {
            "id": "1 2 4",
            "label": "3"
          }
        },
        {
          "data": {
            "id": "1 2 6",
            "label": "5"
          }
        },
        {
          "data": {
            "id": "1 3 5",
            "label": "4"
          }
        },
        {
          "data": {
            "id": "1 3 7",
            "label": "6"
          }
        },
        {
          "data": {
            "id": "1 2 6 9867874",
            "label": "7"
          }
        },
        {
          "data": {
            "id": "1 2 6 7398789",
            "label": "8"
          }
        },
        {
          "data": {
            "id": "1 2 6 9484789",
            "label": "11"
          }
        },
        {
          "data": {
            "source": "1",
            "target": "1 2",
            "id": "c4881f18-03cf-4ed1-bbc4-1741007f11c5"
          }
        },
        {
          "data": {
            "source": "1",
            "target": "1 3",
            "id": "3cc5a94a-0192-4ea2-bdc6-ce1a157b76d4"
          }
        },
        {
          "data": {
            "source": "1 2",
            "target": "1 2 4",
            "id": "1baf1bc6-eb40-4c81-b137-27cdd3a15e60"
          }
        },
        {
          "data": {
            "source": "1 2",
            "target": "1 2 6",
            "id": "78af38cc-7609-401c-bbff-ebdb3f67ec14"
          }
        },
        {
          "data": {
            "source": "1 3",
            "target": "1 3 5",
            "id": "a1c80f9f-7c4b-455c-8ba9-ef5dce5522b5"
          }
        },
        {
          "data": {
            "source": "1 3",
            "target": "1 3 7",
            "id": "85ed3ee9-fdd1-4874-8e36-484db46bf1c5"
          }
        },
        {
          "data": {
            "source": "1 2 6",
            "target": "1 2 6 9867874",
            "id": "f139548a-abca-412b-9935-740f219a938d"
          }
        },
        {
          "data": {
            "source": "1 2 6",
            "target": "1 2 6 7398789",
            "id": "ec8dd60c-df49-447f-b85a-4ae00cde1ae9"
          }
        },
        {
          "data": {
            "source": "1 2 6",
            "target": "1 2 6 9484789",
            "id": "9b5ecc61-d0ca-4872-a2a4-4fd72835345e"
          }
        }
      ]
    )

    return () => {
      document.querySelector("#root")?.removeEventListener("mouseup", clearDragQuestionId);
      plusesContainer.current?.remove();
      crossesContainer.current?.remove();
      gearsContainer.current?.remove();
    };
  }, []);


  const removeButtons = (id: string) => {
    plusesContainer.current
      ?.querySelector(`.popper-plus[data-id='${id}']`)
      ?.remove();
    crossesContainer.current
      ?.querySelector(`.popper-cross[data-id='${id}']`)
      ?.remove();
    gearsContainer.current
      ?.querySelector(`.popper-gear[data-id='${id}']`)
      ?.remove();
  };

  const initialCS = () => {
    const cy = cyRef.current;
    const container =
      (document.body.querySelector(
        ".__________cytoscape_container"
      ) as HTMLDivElement) || null;

    if (!container) {
      return;
    }

    container.style.overflow = "hidden";

    if (!plusesContainer.current) {
      plusesContainer.current = document.createElement("div");
      plusesContainer.current.setAttribute("id", "popper-pluses");
      container.append(plusesContainer.current);
    }
    if (!crossesContainer.current) {
      crossesContainer.current = document.createElement("div");
      crossesContainer.current.setAttribute("id", "popper-crosses");
      container.append(crossesContainer.current);
    }
    if (!gearsContainer.current) {
      gearsContainer.current = document.createElement("div");
      gearsContainer.current.setAttribute("id", "popper-gears");
      container.append(gearsContainer.current);
    }


    cy?.nodes()
      .toArray()
      ?.forEach((item) => {
        const node = item as NodeSingularWithPopper;

        const plusesPopper = node.popper({
          popper: {
            placement: "right",
            modifiers: [{ name: "flip", options: { boundary: node } }],
          },
          content: ([item]) => {
            const itemId = item.id();
            const itemElement = plusesContainer.current?.querySelector(
              `.popper-plus[data-id='${itemId}']`
            );
            if (itemElement) {
              return itemElement;
            }

            const plusElement = document.createElement("div");
            plusElement.classList.add("popper-plus");
            plusElement.setAttribute("data-id", item.id());
            plusesContainer.current?.appendChild(plusElement);
            plusElement.addEventListener("mouseup", () =>
              setStartCreate(node.id())
            );

            return plusElement;
          },
        });

        const crossesPopper = node.popper({
          popper: {
            placement: "top-end",
            modifiers: [
              { name: "flip", options: { boundary: node } },
              {
                name: "hide",
                options: { enabled: true },
              },
            ],
          },
          content: ([item]) => {
            const itemId = item.id();
            const itemElement = crossesContainer.current?.querySelector(
              `.popper-cross[data-id='${itemId}']`
            );
            if (itemElement) {
              return itemElement;
            }

            const crossElement = document.createElement("div");
            crossElement.classList.add("popper-cross");
            crossElement.setAttribute("data-id", item.id());
            crossesContainer.current?.appendChild(crossElement);
            crossElement.addEventListener("click", () => {

              console.log('#' + node.id() + ' node', cy.edges('[source = "' + node.id() + '"]'))
              console.log('[source = "' + node.id() + '"]')
              console.log(cy?.collection)

              // cy?.remove('[source = "'+node.id()+'"]')
              console.log("папа")
              console.log(cy?.$('[target = "' + node.id() + '"]').data().source)


              cy?.remove('#' + node.id())

              // setStartRemove(node.id())
            }


            );
            node.on('remove', evt => {
              console.log(cy.edges())
              // cy?.remove('#'+evt.target.target())
            })

            return crossElement;
          },
        });

        const gearsPopper = node.popper({
          popper: {
            placement: "left",
            modifiers: [{ name: "flip", options: { boundary: node } }],
          },
          content: ([item]) => {
            const itemId = item.id();
            // if (item.id() === elements[0].data.id) {
            //   return;
            // }

            const itemElement = gearsContainer.current?.querySelector(
              `.popper-gear[data-id='${itemId}']`
            );
            if (itemElement) {
              return itemElement;
            }

            const gearsElement = document.createElement("div");
            gearsElement.classList.add("popper-gear");
            gearsElement.setAttribute("data-id", item.id());
            gearsContainer.current?.appendChild(gearsElement);
            // gearsElement.addEventListener("click", () =>
            // setOpenedModalSettings(
            //   findQuestionById(quiz, node.id().split("_").pop() || "").index
            // )
            // );
            return gearsElement;
          },
        });

        const update = async () => {
          await plusesPopper.update();
          await crossesPopper.update();
          await gearsPopper.update();
        };

        const onZoom = (event: AbstractEventObject) => {
          const zoom = event.cy.zoom();

          update();

          crossesPopper.setOptions({
            modifiers: [
              { name: "flip", options: { boundary: node } },
              { name: "offset", options: { offset: [-5 * zoom, -30 * zoom] } },
              {
                name: "hide",
                options: { enabled: true },
              },
            ],
          });

          plusesContainer.current
            ?.querySelectorAll("#popper-pluses > .popper-plus")
            .forEach((item) => {
              const element = item as HTMLDivElement;
              element.style.width = `${40 * zoom}px`;
              element.style.height = `${40 * zoom}px`;
              element.style.fontSize = `${40 * zoom}px`;
              element.style.borderRadius = `${6 * zoom}px`;
            });

          crossesContainer.current
            ?.querySelectorAll("#popper-crosses > .popper-cross")
            .forEach((item) => {
              const element = item as HTMLDivElement;
              element.style.width = `${24 * zoom}px`;
              element.style.height = `${24 * zoom}px`;
              element.style.fontSize = `${24 * zoom}px`;
              element.style.borderRadius = `${6 * zoom}px`;
            });

          gearsContainer.current
            ?.querySelectorAll("#popper-gears > .popper-gear")
            .forEach((item) => {
              const element = item as HTMLDivElement;
              element.style.width = `${33 * zoom}px`;
              element.style.height = `${14 * zoom}px`;
              element.style.fontSize = `${24 * zoom}px`;
            });
        };

        node?.on("position", update);
        cy?.on("pan zoom resize render", onZoom);
      });
  };

  return (
    <CytoscapeComponent
      wheelSensitivity={0.1}
      elements={[]}
      // elements={createGraphElements(tree, quiz)}
      style={{ height: "480px", background: "#F2F3F7" }}
      layout={{
        name: 'preset',
      
        positions: (e) => {
          const id = e.id()
          const incomming = e.cy().edges(`[target="${id}"]`)
          const layer = 0
          e.removeData('lastChild')

          if (incomming.length === 0) {
            const children = e.cy().edges(`[source="${id}"]`)
            e.data('layer', layer)
            e.data('children', children.targets().length)
            const queue = []
            children.forEach(n => {
              queue.push({task: n.target(), layer: layer+1})
            })
            while (queue.length) {
              const task = queue.pop()
              task.task.data('layer', task.layer)
              const children = e.cy().edges(`[source="${task.task.id()}"]`)
              task.task.data('children', children.targets().length)
              if (children.length !== 0) {
                children.forEach(n => queue.push({task: n.target(), layer: task.layer+1}))
              }
            }
            queue.push({parent: e, children:children.targets()})
            while (queue.length) {
              const task = queue.pop()
              if (task.children.length === 0) {
                task.parent.data('subtreeWidth', task.parent.height())
                continue
              }
              const unprocessed = task?.children.filter(e => e.data('subtreeWidth') === undefined)
              if (unprocessed.length !== 0) {
                unprocessed.forEach(t => queue.push({parent:t, children:t.cy().edges(`[source="${t.id()}"]`).targets()}))
                continue
              }
              task?.parent.data('subtreeWidth',task.children.reduce((p,n)=>p+n.data('subtreeWidth'),0))
            }
            return {x:200*e.data('layer'),y:0}
          } else {
            const parent = e.cy().edges(`[target="${e.id()}"]`)[0].source()
           // console.log(e.data('subtreeWidth'), e.id(),(parent.data('children')-1) )
            const wing = parent.data('subtreeWidth')/2
            const lastOffset = parent.data('lastChild')
            const step = wing*2/(parent.data('children')-1)
            if (e.data('layer') === 1)
            console.log(e.data('subtreeWidth'), e.id(),(parent.data('children')-1), step, wing, e.data('layer'), parent.id(), lastOffset)
            //e.removeData('subtreeWidth')
            //console.log('poss', e.id(), 'children', parent.data('children'),'lo', lastOffset, 'v', wing)
            if (lastOffset !== undefined) {
              parent.data('lastChild', lastOffset+step)
              return {x:200*e.data('layer'),y: lastOffset+step}
            } else {
              parent.data('lastChild',parent.position().y - wing)
              return {x:200*e.data('layer'),y: parent.position().y - wing}
            }
          }
        }, // map of (node id) => (position obj); or function(node){ return somPos; }
        zoom: undefined, // the zoom level to set (prob want fit = false if set)
        pan: undefined, // the pan level to set (prob want fit = false if set)
        fit: false, // whether to fit to viewport
        padding: 30, // padding on fit
        animate: false, // whether to transition the node positions
        animationDuration: 500, // duration of animation in ms if enabled
        animationEasing: undefined, // easing of animation if enabled
        animateFilter: function ( node, i ){ return true; }, // a function that determines whether the node should be animated.  All nodes animated by default on animate enabled.  Non-animated nodes are positioned immediately when the layout starts
        ready: (e) => console.log('ready',e), // callback on layoutready
        stop: (e) => console.log('stop',e), // callback on layoutstop
        transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts
      }}
      stylesheet={stylesheet}
      cy={(cy) => {
        cyRef.current = cy;
      }}
    />
  );
};
