import { create } from "zustand";
import {
  addEdge,
  applyEdgeChanges,
  applyNodeChanges,
  Connection,
  Edge,
  EdgeChange,
  Node,
  NodeChange,
  OnConnect,
  OnEdgesChange,
  OnNodesChange,
  useViewport,
  Viewport,
} from "reactflow";

type FlowState = {
  toObject: () => any;
  addNodes: (nodes: Node[]) => void;
  addEdges: (edges: Edge[]) => void;
  nodes: Node[];
  edges: Edge[];
  onNodesChange: OnNodesChange;
  onEdgesChange: OnEdgesChange;
  onConnect: OnConnect;
};

type Storage = {
  nodes: FlowState["nodes"];
  edges: FlowState["edges"];
};

// define the initial state
const initialState: Storage = {
  nodes: [],
  edges: [],
};

const useStore = create<FlowState & Storage>()((set, get) => ({
  ...initialState,

  // Convert the flowchart to an object
  toObject: () => {
    const { nodes, edges } = get();
    return {
      nodes,
      edges,
    };
  },
  addNodes: (_nodes: Node[]) => {
    // Add the new nodes to the existing nodes
    const nodes = [...get().nodes, ..._nodes];
    set({ nodes });
  },
  addEdges: (edges: Edge[]) => {
    // Add the new edges to the existing edges
    const _edges = [...get().edges, ...edges];
    set({ edges: _edges });
  },

  // Apply changes to React Flow when the flowchart is interacted with
  onNodesChange: (changes: NodeChange[]) => {
    set({
      nodes: applyNodeChanges(changes, get().nodes),
    });
  },
  onEdgesChange: (changes: EdgeChange[]) => {
    set({
      edges: applyEdgeChanges(changes, get().edges),
    });
  },
  onConnect: (connection: Connection) => {
    set({
      edges: addEdge(connection, get().edges),
    });
  },
}));

export { useStore };
