import time
import random
from Displays import *
from Buzzer import *
from Button import *
from LightStrip import *
from Log import *


# Game Constants
MAX_SCORE = 10
BALL_SPEEDS = [0.3, 0.5, 0.7]  # Different speeds for ball movement

# Game Classes

class DisplayManager:
    def __init__(self, sda_pin, scl_pin):
        self.display = LCDDisplay(sda=sda_pin, scl=scl_pin)
        self.display.reset()

    def update_score(self, player1_score, player2_score):
        self.display.clear()
        self.display.showText(f"P1: {player1_score}", 0, 0)
        self.display.showText(f"P2: {player2_score}", 1, 0)

    def show_message(self, message):
        self.display.clear()
        self.display.showText(message, 0, 0)


class SoundManager:
    def __init__(self, pin):
        self.buzzer = PassiveBuzzer(pin)

    def play_hit_sound(self):
        self.buzzer.play(500)
        time.sleep(0.1)
        self.buzzer.stop()

    def play_miss_sound(self):
        self.buzzer.play(300)
        time.sleep(0.2)
        self.buzzer.stop()

    def play_foul_sound(self):
        self.buzzer.play(100)
        time.sleep(0.3)
        self.buzzer.stop()


class Ball:
    def __init__(self, pin, num_leds=8):
        self.light_strip = LightStrip(pin, 'neo', num_leds)
        self.position = 0
        self.direction = 1  # 1 for right, -1 for left
        self.speed = random.choice(BALL_SPEEDS)

    def reset_position(self, starting_position):
        self.position = starting_position
        self.direction = 1 if starting_position == 0 else -1
        self.light_strip.off()
        self.light_strip.setPixel(self.position, (0, 255, 0))

    def move(self):
        self.light_strip.off()
        self.position += self.direction
        if self.position >=0 and self.position <=7:
            self.light_strip.setPixel(self.position, (0, 255, 0))

        # Randomly adjust speed to make the game interesting
        if random.random() > 0.8:
            self.speed = random.choice(BALL_SPEEDS)

        time.sleep(self.speed)


class Player:
    def __init__(self, name, position):
        self.name = name
        self.position = position
        self.score = 0

    def increment_score(self):
        self.score += 1

    def reset_score(self):
        self.score = 0


class ButtonHandler:
    def __init__(self, game_controller):
        self.game_controller = game_controller

    def buttonPressed(self, name):
        self.game_controller.handle_button_press(name)

    def buttonReleased(self, name):
        pass  # We only care about button presses for this game.


class GameController:
    def __init__(self):
        # Initialize Components
        self.display = DisplayManager(sda_pin=0, scl_pin=1)
        self.sound = SoundManager(pin=16)
        self.ball = Ball(pin=2)
        
        # Player instances
        self.player1 = Player(name="player1", position=0)
        self.player2 = Player(name="player2", position=7)
        
        # Buttons for each player
        self.button_handler = ButtonHandler(self)
        self.player1_button = Button(pin=3, name="player1", handler=self.button_handler)
        self.player2_button = Button(pin=4, name="player2", handler=self.button_handler)
        
        # Game state
        self.server = self.player1  # Player who serves
        self.running = False
        self.update_display_score()
        self.new_round()

    def update_display_score(self):
        self.display.update_score(self.player1.score, self.player2.score)

    def new_round(self):
        self.display.show_message(f"{self.server.name} to Serve")
        self.ball.reset_position(self.server.position)

    def handle_button_press(self, player_name):
        # Start game movement if server presses
        if not self.running and player_name == self.server.name:
            self.start_ball_movement()
            return
        Log.d(f'press from {player_name}')
        # Check for hit or foul
        player = self.player1 if player_name == "player1" else self.player2
        if player.position == self.ball.position:
            self.handle_hit(player)
        else:
            self.handle_foul(player)

    def start_ball_movement(self):
        self.running = True
        while self.running:
            self.ball.move()
            if self.ball.position < self.player1.position:
                self.handle_miss(self.player2)
            elif self.ball.position > self.player2.position:
                self.handle_miss(self.player1)

    def handle_hit(self, player):
        self.sound.play_hit_sound()
        self.ball.direction *= -1  # Reverse ball direction

    def handle_miss(self, player):
        self.sound.play_miss_sound()
        opponent = self.player1 if player == self.player2 else self.player2
        self.update_score(opponent)
        self.running = False
        self.new_round()

    def handle_foul(self, player):
        self.sound.play_foul_sound()
        opponent = self.player1 if player == self.player2 else self.player2
        self.update_score(opponent)
        self.running = False
        self.new_round()

    def update_score(self, player):
        player.increment_score()
        self.update_display_score()
        
        # Check for game over
        if player.score >= MAX_SCORE:
            self.display.show_message(f"{player.name} Wins!")
            self.running = False

# Initialize Game
game = GameController()
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT