use serde::{Deserialize, Serialize};
use web_time::{SystemTime, UNIX_EPOCH};

use crate::StateTransition;
use crate::context::Context;
use crate::font::FontSize;
use crate::screen::Screen;
use crate::util::refresh_page;
use macroquad::prelude::*;

#[derive(Serialize, Debug)]
#[serde(tag = "type")]
pub enum PlayerClientMessages {
    BuzzIn { time: f64 },
}

#[derive(Deserialize, Debug)]
#[serde(tag = "type")]
pub enum PlayerServerMessages {
    Ack,
    UpdatePointTotal { score: i32 },
    ResetBuzzer,
    ExitGame,
}

#[derive(Default)]
pub struct PlayerScreen {
    score: i32,
    button_pressed: bool,
}

impl Screen for PlayerScreen {
    fn handle_messages(&mut self, ctx: &mut Context) -> Option<StateTransition> {
        let msg = ctx.recv_msg();

        if let Some(msg) = msg {
            match msg {
                PlayerServerMessages::Ack => {
                    info!("Button pressed ack");
                    self.button_pressed = true;
                }
                PlayerServerMessages::ResetBuzzer => {
                    info!("Button press reset");
                    self.button_pressed = false;
                }
                PlayerServerMessages::UpdatePointTotal { score } => {
                    info!("Score updated to: {}", score);
                    self.score = score;
                }
                PlayerServerMessages::ExitGame => {
                    info!("Exiting Game");
                    refresh_page();
                }
            }
        }

        None
    }

    fn handle_frame(&mut self, ctx: &mut Context) {
        clear_background(BEIGE);

        let button_color = if self.button_pressed {
            Color::from_hex(0xaa0000)
        } else {
            RED
        };

        let text_measure = FontSize::Large.measure(&ctx.username);

        draw_text(
            &ctx.username,
            screen_width() * 0.5 - text_measure.width * 0.5,
            screen_height() * 0.15,
            FontSize::Large.size() as f32,
            BLACK,
        );

        let score_text = format!("Score: {}", self.score);
        let text_measure = FontSize::Large.measure(&score_text);

        draw_text(
            &score_text,
            screen_width() * 0.5 - text_measure.width * 0.5,
            screen_height() * 0.25,
            FontSize::Large.size() as f32,
            BLACK,
        );

        let button_size = (screen_width() * 0.33).min(screen_height() * 0.20);
        draw_circle(
            screen_width() * 0.5,
            screen_height() * 0.5,
            button_size * 1.1,
            DARKBROWN,
        );
        draw_circle(
            screen_width() * 0.5,
            screen_height() * 0.5,
            button_size,
            button_color,
        );

        if !self.button_pressed && is_mouse_button_pressed(MouseButton::Left) {
            let loc = Vec2::from(mouse_position());
            let normalize = loc - Vec2::new(screen_width() * 0.5, screen_height() * 0.5);

            if normalize.length() < button_size {
                let timestamp = SystemTime::now();
                let unix_timestamp = timestamp.duration_since(UNIX_EPOCH).expect("Time invalid");

                let time = unix_timestamp.as_secs_f64();

                info!("Button pressed @ {}", time);
                ctx.send_msg(&PlayerClientMessages::BuzzIn { time });
            }
        }
    }
}
