const videoElement = document.getElementById('webcam');
const canvasElement = document.getElementById('output_canvas');
const canvasCtx = canvasElement.getContext('2d');
const virtualCursor = document.getElementById('virtual-cursor');

let lastGesture = "";
let hoverTimer;
let currentHoverElement = null;

let lastScrollTime = 0;
let pauseTimer = null;
let gestureChangeTimestamp = 0;

let onboardingComplete = localStorage.getItem("onboarding_done") === "true";
let currentStep = 1;

let smoothedX = 0.5;
let smoothedY = 0.5;
const SMOOTHING_FACTOR = 0.50;

window.addEventListener("DOMContentLoaded", () => {
    const onboardingScreen = document.getElementById("onboardingScreen");
    const startScreen = document.getElementById("startScreen");

    if (onboardingComplete) {
        startScreen.style.display = "flex";
        onboardingScreen.style.display = "none";
    } else {
        onboardingScreen.style.display = "flex";
        startScreen.style.display = "none";
    }
});

const hands = new Hands({
    locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`
});

const THRESHOLD = {
    min: 0.40,
    max: 0.60
};

hands.setOptions({
    maxNumHands: 1,
    modelComplexity: 1,
    minDetectionConfidence: 0.5,
    minTrackingConfidence: 0.5
});

hands.onResults(onResults);

function onResults(results) {
    canvasCtx.save();
    canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
    canvasCtx.drawImage(results.image, 0, 0, canvasElement.width, canvasElement.height);

    drawGuides();

    let gestureText = "Tidak Ada";
    let accuracyText = "0%";
    let angleText = "0°";

    if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) {
        const confidence = (results.multiHandedness[0].score * 100).toFixed(1);
        accuracyText = confidence + "%";

        if (!onboardingComplete) {
            if (currentStep === 1) {
                const statusBox = document.getElementById("cameraStatus");
                if (statusBox && !statusBox.classList.contains("ready")) {
                    statusBox.innerText = "Tangan Terdeteksi";
                    statusBox.classList.add("ready");
                    setTimeout(() => {
                        if (currentStep === 1 && !onboardingComplete) {
                            nextOnboardingStep(2);
                        }
                    }, 1000);
                }
            }
        }

        for (const landmarks of results.multiHandLandmarks) {
            drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS, {color: '#FFFFFF', lineWidth: 2});
            drawLandmarks(canvasCtx, landmarks, {color: '#6AB04A', lineWidth: 2, radius: 2});

            const wrist = landmarks[0];
            const middleMcp = landmarks[9];
            const rad = Math.atan2(middleMcp.y - wrist.y, middleMcp.x - wrist.x);
            let angle = Math.round(rad * (180 / Math.PI));

            angle = (angle + 90) % 360; 
            angleText = angle + "°";

            const indexFinger = landmarks[8];
            const thumbTip = landmarks[4];
            const pinkyTip = landmarks[20];

            const guidePopup = document.getElementById("guidePopup");
            if (guidePopup.style.display === "flex") {
                handleScrollInteraction(indexFinger.y);
            }

            const handSpan = Math.hypot(thumbTip.x - pinkyTip.x, thumbTip.y - pinkyTip.y);

            if (isGameRunning() && !isPaused && !isGameOver && handSpan > 0.2) {
                if (!pauseTimer) {
                    pauseTimer = setTimeout(() => {
                        togglePause();
                        pauseTimer = null;
                    }, 1000); 
                }
            } else {
                clearTimeout(pauseTimer);
                pauseTimer = null;
            }

            if (!isGameRunning() || isPaused && !isCountingDown) {
                if (virtualCursor) {
                    virtualCursor.style.display = 'block';

                    smoothedX = smoothedX + (indexFinger.x - smoothedX) * SMOOTHING_FACTOR;
                    smoothedY = smoothedY + (indexFinger.y - smoothedY) * SMOOTHING_FACTOR;

                    const cursorX = (1 - smoothedX) * window.innerWidth;
                    const cursorY = smoothedY * window.innerHeight;
                    
                    virtualCursor.style.left = cursorX + 'px';
                    virtualCursor.style.top = cursorY + 'px';
                    
                    handleMenuInteraction(cursorX, cursorY);
                }
            } else {
                if (virtualCursor) virtualCursor.style.display = 'none';
                resetHover();
            }
            gestureText = getActiveDirection(indexFinger.x, indexFinger.y) || "Tengah";
            processGesture(indexFinger.x, indexFinger.y);
        }
    } else {
        if (virtualCursor) virtualCursor.style.display = 'none';
        resetHover();
    }
    document.getElementById("current-gesture").innerText = gestureText;
    document.getElementById("current-accuracy").innerText = accuracyText;
    document.getElementById("game-angle").innerText = angleText;

    canvasCtx.restore();
}

function handleMenuInteraction(x, y) {
    const element = document.elementFromPoint(x, y);
    
    if (element && element.tagName === "BUTTON") {
        if (currentHoverElement !== element) {
            resetHover();
            currentHoverElement = element;
            element.classList.add('finger-hover');
            
            hoverTimer = setTimeout(() => {
                element.click();
                resetHover();
            }, 1000);
        }
    } else {
        resetHover();
    }
}

function handleScrollInteraction(y) {
    const guideBox = document.querySelector(".guide-box");
    if (!guideBox) return;

    const now = Date.now();
    if (now - lastScrollTime < 30) return; 

    if (y < 0.25) { 
        guideBox.scrollTop -= 15;
        lastScrollTime = now;
    }
    else if (y > 0.75) { 
        guideBox.scrollTop += 15;
        lastScrollTime = now;
    }
}

function resetHover() {
    clearTimeout(hoverTimer);
    if (currentHoverElement) {
        currentHoverElement.classList.remove('finger-hover');
        currentHoverElement = null;
    }
}

function getActiveDirection(x, y) {
    if (x < THRESHOLD.min) return "Kanan"; 
    if (x > THRESHOLD.max) return "Kiri";
    if (y < THRESHOLD.min) return "Atas";
    if (y > THRESHOLD.max) return "Bawah";
    return null; 
}

function processGesture(x, y) {
    if (isPaused || isGameOver || !isGameRunning()) return;

    let newDir = null;
    let sound = null;

    if (x < THRESHOLD.min) { 
        newDir = { x: 1, y: 0 }; sound = rightSound;
    } else if (x > THRESHOLD.max) { 
        newDir = { x: -1, y: 0 }; sound = leftSound;
    } 
    else if (y < THRESHOLD.min) { 
        newDir = { x: 0, y: -1 }; sound = upSound;
    } else if (y > THRESHOLD.max) { 
        newDir = { x: 0, y: 1 }; sound = downSound;
    } else {
        lastGesture = "Tengah";
        return;
    }

    const gestureLabel = getActiveDirection(x, y);
    if (lastGesture !== gestureLabel) {
        lastGesture = gestureLabel;
        gestureChangeTimestamp = performance.now();
        handleGestureInput(newDir, sound);
    }
}

function handleGestureInput(newDir, sound) {
    let lastDir = directionQueue.length > 0 
        ? directionQueue[directionQueue.length - 1] 
        : velocity;

    if (lastDir.x === 0 && lastDir.y === 0) {
        if (newDir.x === -1) return;
    } else {
        if (newDir.x === -lastDir.x && newDir.y === -lastDir.y) return;
    }

    if (newDir.x === lastDir.x && newDir.y === lastDir.y) return;

    playSound(sound);
    if (directionQueue.length < 3) { 
        directionQueue.push(newDir);
    }
}

function drawGuides() {
    const w = canvasElement.width;
    const h = canvasElement.height;

    canvasCtx.strokeStyle = "#FFFFFF";
    canvasCtx.lineWidth = 1;

    canvasCtx.beginPath();
    canvasCtx.moveTo(w / 2, 0); canvasCtx.lineTo(w / 2, h);
    canvasCtx.moveTo(0, h / 2); canvasCtx.lineTo(w, h / 2);
    canvasCtx.stroke();

    canvasCtx.strokeStyle = "#E7471D";
    canvasCtx.strokeRect(
        w * THRESHOLD.min, 
        h * THRESHOLD.min, 
        w * (THRESHOLD.max - THRESHOLD.min), 
        h * (THRESHOLD.max - THRESHOLD.min)
    );
}

function nextOnboardingStep(step) {
    currentStep = step;
    document.querySelectorAll('.onboarding-step').forEach(el => el.style.display = 'none');
    const targetStep = document.getElementById(`step${step}`);
    if (targetStep) {
        targetStep.style.display = 'block';
    } else {
        finishOnboarding();
    }
}

function finishOnboarding() {
    onboardingComplete = true;
    localStorage.setItem("onboarding_done", "true"); 
    document.getElementById("onboardingScreen").style.display = "none";
    document.getElementById("startScreen").style.display = "flex";
}

const camera = new Camera(videoElement, {
    onFrame: async () => { await hands.send({ image: videoElement }); },
    width: 300, height: 200
});
camera.start();