import { useEffect, useState, useRef, useCallback } from "react";
import ForceGraph3D from "react-force-graph-3d";
import graphData from "../data.json";
import SpriteText from "https://esm.sh/three-spritetext";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faInfoCircle, faExternalLinkAlt, faChevronLeft, faChevronRight } from "@fortawesome/free-solid-svg-icons";

export default function GraphComponent({ selectedCategory }) {
  const fgRef = useRef();
  const [selectedNode, setSelectedNode] = useState(null);
  const [graphDataState, setGraphDataState] = useState({ nodes: [], links: [] });
  const [imageIndex, setImageIndex] = useState(0);  // State to track current image in the carousel

  // Set distance from camera orbit
  const distance = 400;
  const speed = 0.3;

  useEffect(() => {
    // Clone the original graph data to avoid modifying it directly
    const updatedGraphData = {
      nodes: graphData.nodes.map(node => ({
        ...node,
        visible: !selectedCategory || node.category === selectedCategory // Hide nodes not in selected category
      })),
      links: graphData.links.map(link => ({
        ...link,
        visible:
          (!selectedCategory ||
            (graphData.nodes.find(n => n.id === link.source)?.category === selectedCategory &&
             graphData.nodes.find(n => n.id === link.target)?.category === selectedCategory)) // Hide links if either connected node is hidden
      }))
    };

    setGraphDataState(updatedGraphData);

    // Camera orbit logic
    const cameraOrbit = () => {
      let angle = 0;
      fgRef.current.cameraPosition({ z: distance });

      // Set interval for camera orbit effect
      const intervalId = setInterval(() => {
        fgRef.current.cameraPosition({
          x: distance * Math.sin(angle),
          z: distance * Math.cos(angle)
        });
        angle += (Math.PI / 300) * speed;
      }, 10);

      // Clear up the interval when the component is unmounted
      return () => clearInterval(intervalId);
    };

    // Call camera orbit after the graph is set
    const cleanupCameraOrbit = cameraOrbit();

    return cleanupCameraOrbit;
  }, [selectedCategory]);

  const handleNodeClick = useCallback((node) => {
    setSelectedNode(node);
    setImageIndex(0);  // Reset the image index when a new node is clicked
  }, []);

  const handleBackgroundClick = useCallback(() => {
    setSelectedNode(null);
  }, []);

  // Carousel navigation functions
  const prevImage = () => {
    if (selectedNode && selectedNode.image && Array.isArray(selectedNode.image)) {
      setImageIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : selectedNode.image.length - 1));
    }
  };

  const nextImage = () => {
    if (selectedNode && selectedNode.image && Array.isArray(selectedNode.image)) {
      setImageIndex((prevIndex) => (prevIndex < selectedNode.image.length - 1 ? prevIndex + 1 : 0));
    }
  };

  return (
    <div className="relative">
      {/* Information Window Wrapper */}
      {selectedNode && (
        <div className="bg-gray-700 rounded-lg shadow-md z-10 
          absolute left-[50%] top-[50%] transform-gpu -translate-x-1/2 -translate-y-1/2 p-4 h-[max-content] max-h-[80%]">
          {/* Image and Description */}
          <div className="rounded-sm flex flex-row h-[100%] w-[100%] space-x-4">
            {/* Image Section */}
            {selectedNode.image && (
              <div className="flex flex-col justify-center items-center relative">
                {/* If it's an array of images, render carousel */}
                {Array.isArray(selectedNode.image) ? (
                  <div className="relative">
                    <img
                      className="rounded-sm object-contain w-[100%] h-auto"
                      src={selectedNode.image[imageIndex]}
                      alt={`${selectedNode.name} - Image ${imageIndex + 1}`}
                    />
                    {/* Left and Right Chevron Buttons */}
                    <button
                      className="absolute left-0 top-1/2 transform -translate-y-1/2 text-white text-xl"
                      onClick={prevImage}
                    >
                      <FontAwesomeIcon icon={faChevronLeft} />
                    </button>
                    <button
                      className="absolute right-0 top-1/2 transform -translate-y-1/2 text-white text-xl"
                      onClick={nextImage}
                    >
                      <FontAwesomeIcon icon={faChevronRight} />
                    </button>
                  </div>
                ) : (
                  // Single image
                  <img
                    className="rounded-sm object-contain w-[100%]"
                    src={selectedNode.image}
                    alt={selectedNode.name}
                  />
                )}
              </div>
            )}
            {/* Text Content */}
            <div className="w-[100%] max-w-64ch">
              <div className="flex flex-row space-x-2">
                {/* Title */}
                <h3 className="text-lg font-bold">{selectedNode.name}</h3>
                {/* Info Button fontawesome */}
                {selectedNode.link && (
                  <div className="flex space-x-2 ml-2">
                    <button className="text-[rgba(255,255,255,0.5)] text-sm">
                      <FontAwesomeIcon icon={faInfoCircle} />
                    </button>
                    <button className="hover:text-white text-[rgba(255,255,255,0.5)] text-sm">
                      <a href={selectedNode.link} target="_blank" rel="noreferrer">
                        <FontAwesomeIcon icon={faExternalLinkAlt} />
                      </a>
                    </button>
                  </div>
                )}
              </div>
              <h6 className="text-xs text-gray-400 mb-2">{selectedNode.location.city} | {selectedNode.location.state} | {selectedNode.location.country}</h6>
              {/* Description */}
              <p className="text-sm text-justify">{selectedNode.description}</p>
            </div>
            {/* Close button */}
            <button
              className="self-start hover:text-white text-[rgba(255,255,255,0.5)] text-sm"
              onClick={() => setSelectedNode(null)}
            >
              Close
            </button>
          </div>
        </div>
      )}
    
      {/* ForceGraph3D */}
      <ForceGraph3D
        ref={fgRef}
        graphData={graphDataState}
        nodeAutoColorBy="group"
        nodeThreeObject={node => {
          const sprite = new SpriteText(node.name);
          sprite.color = node.color;
          sprite.textHeight = 8;
          return sprite;
        }}
        linkVisibility={link => link.visible} // Hide links properly
        nodeVisibility={node => node.visible} // Hide nodes properly
        onNodeClick={handleNodeClick}
        onBackgroundClick={handleBackgroundClick}
      />
    </div>
  );
}
