"""Hand tracking game using Pygame."""

import pygame
import cv2
import numpy as np
from hand_tracking.tracker import HandTracker


class HandTrackingGame:
    """A game that uses hand gestures to move a rectangle on the screen."""

    # Direction mapping for gestures
    GESTURE_DIRECTIONS = {
        "up": (0, -1),
        "down": (0, 1),
        "left": (-1, 0),
        "right": (1, 0)
    }

    def __init__(self, screen_width=1280, screen_height=720, model_path=None):
        """
        Initialize the hand tracking game.

        Args:
            screen_width: Width of the game window.
            screen_height: Height of the game window.
            model_path: Path to the pre-trained hand tracking model.
        """
        pygame.init()

        self.screen_width = screen_width
        self.screen_height = screen_height
        self.win = pygame.display.set_mode((screen_width, screen_height))
        pygame.display.set_caption("Hand Tracking Game")

        # Player sprite
        self.player_x = 200
        self.player_y = 200
        self.player_width = 40
        self.player_height = 40
        self.player_velocity = 10

        # Game state
        self.running = True

        # Initialize hand tracker
        self.tracker = HandTracker(model_path=model_path)
        self.cap = cv2.VideoCapture(0)

        if not self.cap.isOpened():
            raise RuntimeError("Failed to open video source")

        # Direction labels for this game
        self.labels_dict = {0: "up", 1: "down", 2: "right", 3: "left"}

    def handle_gesture(self, predicted_character):
        """
        Move the player based on the predicted gesture.

        Args:
            predicted_character: The gesture label (str or None).
        """
        if predicted_character not in self.labels_dict.values():
            return

        dx, dy = self.GESTURE_DIRECTIONS.get(predicted_character, (0, 0))

        new_x = self.player_x + (dx * self.player_velocity)
        new_y = self.player_y + (dy * self.player_velocity)

        # Keep player within bounds
        if 0 <= new_x <= self.screen_width - self.player_width:
            self.player_x = new_x
        if 0 <= new_y <= self.screen_height - self.player_height:
            self.player_y = new_y

        if predicted_character:
            print(f"Gesture detected: {predicted_character}")

    def run(self):
        """Run the game loop."""
        clock = pygame.time.Clock()

        while self.running:
            # Capture from camera
            ret, frame = self.cap.read()
            if not ret:
                print("Failed to grab frame")
                break

            # Get hand gesture prediction
            prediction = self.tracker.predict_gesture(frame)
            self.handle_gesture(prediction['character'])

            # Handle pygame events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False

            # Handle keyboard input (optional)
            keys = pygame.key.get_pressed()
            if keys[pygame.K_LEFT] and self.player_x > 0:
                self.player_x -= self.player_velocity
            if keys[pygame.K_RIGHT] and self.player_x < self.screen_width - self.player_width:
                self.player_x += self.player_velocity
            if keys[pygame.K_UP] and self.player_y > 0:
                self.player_y -= self.player_velocity
            if keys[pygame.K_DOWN] and self.player_y < self.screen_height - self.player_height:
                self.player_y += self.player_velocity

            # Render
            self.win.fill((0, 0, 0))
            pygame.draw.rect(self.win, (255, 0, 0),
                           (self.player_x, self.player_y, self.player_width, self.player_height))
            pygame.display.update()

            clock.tick(30)

        self.cleanup()

    def cleanup(self):
        """Clean up resources."""
        self.cap.release()
        pygame.quit()


def main():
    """Run the hand tracking game."""
    game = HandTrackingGame()
    game.run()


if __name__ == '__main__':
    main()
