import { useMemo, useRef } from 'react'
import * as THREE from 'three';
import MaterialAnimator from '../animator/materialAnimator';
import { MaterialModel } from '../material/materialModel';
import { useThree } from '@react-three/fiber';
import { useAnimationPlaySpeed } from '../../../../../store/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useProductContext } from '../../../products/productContext';
import { useSceneContext } from '../../../../scene/sceneContext';

function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
    const matRef: any = useRef();
    const { scene } = useThree();
    const { selectedProductStore } = useProductContext();
    const { productStore, materialStore } = useSceneContext();
    const { setIsPaused } = materialStore();
    const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid, getActionByPointUuid } = productStore();
    const { selectedProduct } = selectedProductStore();
    const { speed } = useAnimationPlaySpeed();
    const { triggerPointActions } = useTriggerHandler();

    const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => {
        const pointObj = scene.getObjectByProperty("uuid", pointUuid);
        if (!pointObj) return null;

        const worldPosition = new THREE.Vector3();
        pointObj.getWorldPosition(worldPosition);
        return worldPosition;
    };

    const { position, rotation, currentSpeed } = useMemo(() => {
        if (!material.current?.pointUuid) {
            return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 };
        }

        const modelUuid = getModelUuidByPointUuid(selectedProduct.productUuid, material.current.pointUuid);
        if (!modelUuid) {
            return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 };
        }

        const currentSpeed = getCurrentSpeed(selectedProduct.productUuid, modelUuid);

        const point = getPointByUuid(selectedProduct.productUuid, modelUuid, material.current.pointUuid);
        if (!point) {
            return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: currentSpeed || 1 };
        }

        const position = getWorldPositionFromScene(point.uuid);
        if (position) {
            return { position: position, rotation: new THREE.Vector3(0, 0, 0), currentSpeed: currentSpeed || 1 };
        }

        return {
            position: new THREE.Vector3(...point.position),
            rotation: new THREE.Vector3(...point.rotation),
            currentSpeed: currentSpeed || 1
        };
    }, [material, getPointByUuid]);


    function getCurrentSpeed(productUuid: string, modelUuid: string) {
        const event = getEventByModelUuid(productUuid, modelUuid)
        if (event) {
            if (event.type === 'transfer' || event.type === 'machine' || event.type === 'storageUnit') {
                return 1;
            }
            if (event.type === 'vehicle' || event.type === 'roboticArm' || event.type === 'human') {
                return event.speed;
            }
        } else {
            return 1;
        }
    }

    const callTrigger = () => {
        if (material.next) {
            const action = getActionByPointUuid(selectedProduct.productUuid, material.next.pointUuid);
            if (action) {
                triggerPointActions(action, material.materialId);
            }
        } else {
            setIsPaused(material.materialId, true);
        }
    }

    return (
        <>

            {material.isRendered &&
                <MaterialModel materialId={material.materialId} matRef={matRef} materialType={material.materialType} visible={material.isVisible} position={position} rotation={[rotation.x, rotation.y, rotation.z]} />
            }

            <MaterialAnimator
                matRef={matRef}
                material={material}
                currentSpeed={currentSpeed * speed}
                onAnimationComplete={() => { callTrigger() }}
            />
        </>
    )
}

export default MaterialInstance