import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useLoader } from "@react-three/fiber";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { clone } from "three/examples/jsm/utils/SkeletonUtils";
import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
import IKAnimationController from "./IKAnimationController";

const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; position: [number, number, number]; rotation: [number, number, number]; }) => {
    const [ikSolver, setIkSolver] = useState<any>(null);
    const [selectedTrigger, setSelectedTrigger] = useState<string>("idle");
    const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
        const draco = new DRACOLoader();
        draco.setDecoderPath(
            "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/"
        );
        loader.setDRACOLoader(draco);
    });
    const cloned = useMemo(() => clone(gltf.scene), [gltf]);
    const groupRef = useRef<any>(null);
    const [selectedArm, setSelectedArm] = useState<THREE.Group>();
    const targetBoneName = "Target";
    const skinnedMeshName = "link_0";

    const process = useMemo(() => [
        {
            trigger: "Trigger1",
            start: new THREE.Vector3(-0.75, 1.5, -2.2),
            end: new THREE.Vector3(0, 1.2, 2.2),
            speed: 0.25,
        },
        {
            trigger: "Trigger2",
            start: new THREE.Vector3(0, 1.2, 2.2),
            end: new THREE.Vector3(0.75, 1.5, -2.2),
            speed: 0.22,
        }
    ], []);

    useEffect(() => {
        if (!gltf) return;
        const OOI: any = {};
        cloned.traverse((n: any) => {
            if (n.name === targetBoneName) OOI.Target_Bone = n;
            if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n;
        });

        if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return;

        const iks = [
            {
                target: 7,
                effector: 6,
                links: [
                    {
                        index: 5,
                        enabled: true,
                        rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0),
                        rotationMax: new THREE.Vector3(Math.PI / 2, 0, 0),
                    },
                    {
                        index: 4,
                        enabled: true,
                        rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0),
                        rotationMax: new THREE.Vector3(0, 0, 0),
                    },
                    {
                        index: 3,
                        enabled: true,
                        rotationMin: new THREE.Vector3(0, 0, 0),
                        rotationMax: new THREE.Vector3(2, 0, 0),
                    },
                    { index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) },
                    { index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) },
                ],
            },
        ];

        const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
        setIkSolver(solver);

        const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05);
        // groupRef.current.add(helper);

    }, [gltf]);

    useEffect(() => {
        const triggers = ['Trigger1', 'Trigger2'];
        let index = 0;

        const cycleTriggers = setInterval(() => {
            setSelectedTrigger(triggers[index]);
            index = (index + 1) % triggers.length;
        }, 10000);

        return () => clearInterval(cycleTriggers);
    }, []);

    return (
        <>
            <group
                ref={groupRef}
                onClick={(e) => {
                    e.stopPropagation();
                    setSelectedArm(groupRef.current?.getObjectByName(targetBoneName))
                }}
            >
                <primitive
                    object={cloned}
                    position={position}
                    rotation={rotation}
                    scale={[1, 1, 1]}
                    name={`arm-bot`}
                />
            </group>
            <IKAnimationController
                ikSolver={ikSolver}
                process={process}
                selectedTrigger={selectedTrigger}
                targetBoneName={targetBoneName}
            />
            {/* {selectedArm && <TransformControls object={selectedArm} />} */}
        </>
    );
};

export default IkInstances;