from services.predict import PredictService, PredictionSmoother
from services.rpi import RPIService
from models.cards import Card
from game_logic.manager import GameManager, PLAYERS
from game_logic.game_states import GameState
import gradio as gr
import numpy as np
import cv2

FRAMES_PER_SECOND = 20
SMOOTHING_MEMORY_SECONDS = 1

stream_every = 1 / FRAMES_PER_SECOND
smoothing_memory = FRAMES_PER_SECOND * SMOOTHING_MEMORY_SECONDS

rpi_service = RPIService("172.30.248.163")

game_manager = GameManager(rpi_service)
smoother = PredictionSmoother(smoothing_memory)

def start_game(_):
    global game_manager
    game_manager = GameManager()
    return None, None

def end_round(_):
    game_manager.end_round()
    return None, None

def solve_round_error(points: int, team: str):
    game_manager.solve_round_error(points, team)
    return None, None

def choose_trump_symbol(trump_symbol: str, multiplier: int):
    game_manager.start_round(trump_symbol, multiplier)
    return None, None
 
def get_prediction_output(frame):
    frame = cv2.flip(frame, 1)

    lower_green = np.array([0, 0, 0])
    upper_green = np.array([200,200, 200])
    mask = cv2.inRange(frame, lower_green, upper_green)
    frame[mask > 0] = [0, 0, 0]
    data = PredictService.predict_frame(frame)
    cards = PredictService.pair_predictions(data)
    new_value: list[Card] = smoother.add_prediction(cards)

    if new_value:
        game_manager.play_card(new_value)

    symbol_img = data["symbol"].visualization
    value_img = data["value"].visualization
    return symbol_img, value_img, None

with gr.Blocks() as demo:

    gr.Markdown("# The casino cam")

    refresher_box = gr.Textbox(visible=False)
    cam_refresher_box = gr.Textbox(visible=False)

    with gr.Row():
        with gr.Column(scale=1):

            @gr.render(inputs=cam_refresher_box)
            def cam_refresh(_):
                game_state = game_manager.game_state
                if game_state == GameState.ROUND_PLAYING:
                    last_play = game_manager.round.play.play_cards
                    with gr.Row():
                        for i, card in enumerate(last_play):
                            with gr.Column(scale=1):
                                gr.Markdown(f"### {card.value} {card.symbol}")

                elif game_state == GameState.ROUND_ENDED:
                    round_playing_button = gr.Button(value="Start new round")

                    round_playing_button.click(
                        end_round,
                        None,
                        [cam_refresher_box, refresher_box]
                    )

                elif game_state == GameState.ROUND_ERROR:
                    points_choice = gr.Slider(
                        minimum=0,
                        maximum=30,
                        value=0,
                        step=1,
                        label="Points",
                        info="The number of points scored in the round"
                    )

                    team_choice = gr.Dropdown(
                        ["NS", "EW"],
                        label="Team",
                        info="What team got the points"
                    )

                    solve_round_error_button = gr.Button(value="Confirm")

                    solve_round_error_button.click(
                        solve_round_error,
                        [points_choice, team_choice],
                        [refresher_box, cam_refresher_box]
                    )

        with gr.Column(scale=1):

            @gr.render(inputs=refresher_box)
            def refresh(_):
                game_state = game_manager.game_state
                dealer = game_manager.dealer
                if game_state == GameState.ROUND_CREATING:
                    gr.Markdown("## Create Round")
                    gr.Markdown(f"## Dealer = {PLAYERS[dealer]}")

                    trump_card_choice = gr.Dropdown(
                        ["None", "Clubs", "Hearts", "Diamonds", "Spades"],
                        label="Symbol",
                        info="Choose the agreed upon trump symbol"
                    )

                    multiplier_choice = gr.Dropdown(
                        [1, 2, 4],
                        label="Multiplier",
                        info="Choose the agreed upon multiplier"
                    )
                    
                    round_creating_button = gr.Button(value="Confirm")

                    round_creating_button.click(
                        choose_trump_symbol,
                        [trump_card_choice, multiplier_choice],
                        [refresher_box, cam_refresher_box]
                    )

                elif game_state == GameState.ROUND_PLAYING:
                    gr.Markdown(f"## Trump: {game_manager.round.trump_symbol}")

                    input_img = gr.Image(sources=["webcam"], type="numpy", label="Webcam Input")
                    symbol_output = gr.Image(label="Symbol Prediction", streaming=True)
                    value_output = gr.Image(label="Value Prediction", streaming=True)

                    input_img.stream(
                        get_prediction_output, 
                        input_img, 
                        [symbol_output, value_output, cam_refresher_box]
                    )

                elif game_state == GameState.NS_WINS_GAME or game_state == GameState.EW_WINS_GAME:

                    if game_state == GameState.NS_WINS_GAME:
                        gr.Markdown("## NS WINS")
                    elif game_state == GameState.EW_WINS_GAME:
                        gr.Markdown("## EW WINS")

                    restart_button = gr.Button("Start New Game")

                    restart_button.click(
                        start_game,
                        None,
                        [refresher_box, cam_refresher_box]
                    )

demo.launch()