import { useEffect, useRef } from 'react';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';

import MaterialAnimator from '../animator/materialAnimator';
import ManufacturerInstance from './actions/manufacturerInstance';
import WorkerInstance from './actions/workerInstance';
import OperatorInstance from './actions/operatorInstance';

function HumanInstance({ human }: { human: HumanStatus }) {
    const { isPlaying } = usePlayButtonStore();
    const { humanStore, productStore } = useSceneContext();
    const { getActionByUuid } = productStore();
    const { selectedProductStore } = useProductContext();
    const { selectedProduct } = selectedProductStore();
    const { incrementIdleTime, incrementActiveTime } = humanStore();

    const idleTimeRef = useRef<number>(0);
    const activeTimeRef = useRef<number>(0);
    const isPausedRef = useRef<boolean>(false);
    const isSpeedRef = useRef<number>(0);
    const { speed } = useAnimationPlaySpeed();
    const { isPaused } = usePauseButtonStore();
    const previousTimeRef = useRef<number | null>(null);
    const animationFrameIdRef = useRef<number | null>(null);
    const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');

    useEffect(() => {
        isPausedRef.current = isPaused;
    }, [isPaused]);

    useEffect(() => {
        isSpeedRef.current = speed;
    }, [speed]);

    function animate(currentTime: number) {
        if (previousTimeRef.current === null) {
            previousTimeRef.current = currentTime;
        }

        const deltaTime = (currentTime - previousTimeRef.current) / 1000;
        previousTimeRef.current = currentTime;

        if (human.isActive) {
            if (!isPausedRef.current) {
                activeTimeRef.current += deltaTime * isSpeedRef.current;
            }
        } else {
            if (!isPausedRef.current) {
                idleTimeRef.current += deltaTime * isSpeedRef.current;
            }
        }
        animationFrameIdRef.current = requestAnimationFrame(animate);
    }

    useEffect(() => {
        if (!isPlaying) return
        if (!human.isActive) {
            const roundedActiveTime = Math.round(activeTimeRef.current);
            incrementActiveTime(human.modelUuid, roundedActiveTime);
            activeTimeRef.current = 0;
        } else {
            const roundedIdleTime = Math.round(idleTimeRef.current);
            incrementIdleTime(human.modelUuid, roundedIdleTime);
            idleTimeRef.current = 0;
        }

        if (animationFrameIdRef.current === null) {
            animationFrameIdRef.current = requestAnimationFrame(animate);
        }

        return () => {
            if (animationFrameIdRef.current !== null) {
                cancelAnimationFrame(animationFrameIdRef.current);
                animationFrameIdRef.current = null;
            }
        };
    }, [human, isPlaying]);

    return (
        <>

            {action && action.actionType === 'worker' &&
                <WorkerInstance human={human} />
            }
            {action && action.actionType === 'manufacturer' &&
                <ManufacturerInstance human={human} />
            }
            {action && action.actionType === 'operator' &&
                <OperatorInstance human={human} />
            }

            <MaterialAnimator human={human} />
        </>
    )
}

export default HumanInstance