use gtk::prelude::*;
use crate::state::{MODULE_STATE, WindowData};
use crate::context::WindowContext;

const PLAYER_POOL_SIZE: usize = 3;

pub struct WindowHandler;

impl WindowHandler {
    pub unsafe fn create(ctx: &WindowContext) {
        println!("[ahfail] on_window_create called");

        let error_label = ctx.get_error_label();
        let overlay = ctx.get_overlay();
        let monitor = ctx.get_monitor();

        let geom = monitor.geometry();
        let screen_w = geom.width();
        let screen_h = geom.height();

        let fixed = gtk::Fixed::new();
        fixed.set_size_request(screen_w, screen_h);
        fixed.set_halign(gtk::Align::Fill);
        fixed.set_valign(gtk::Align::Fill);
        fixed.set_hexpand(true);
        fixed.set_vexpand(true);
        
        overlay.add_overlay(&fixed);
        overlay.set_overlay_pass_through(&fixed, true);

        let mut ready_players = Vec::new();
        MODULE_STATE.with(|state| {
            if let Some(audio_uri) = &state.borrow().audio_uri {
                for _ in 0..PLAYER_POOL_SIZE {
                    ready_players.push(ahfail_ui::audio::create_player(audio_uri));
                }
            }
        });

        let data = Box::new(WindowData {
            sprites: Vec::new(),
            active_players: Vec::new(),
            ready_players,
            fixed: fixed.clone(),
            signal_id: None,
        });

        ctx.set_data(data);
        let ptr_addr = ctx.get_data_ptr() as usize;

        let signal_id = error_label.connect_notify(Some("label"), move |label, _| {
            let text = label.text();
            let text_str = text.as_str();
            if text_str.is_empty() {
                return;
            }
            println!("[ahfail] Error label changed to: '{}'", text_str);

            MODULE_STATE.with(|s| {
                let mut st = s.borrow_mut();
                if st.volume_state.is_none() {
                    st.volume_state = ahfail_ui::volume::save_and_set_max();
                }
            });

            MODULE_STATE.with(|state| {
                let state = state.borrow();
                if let (Some(animation), Some(audio_uri)) = (&state.animation, &state.audio_uri) {
                    let data = unsafe { &mut *(ptr_addr as *mut WindowData) };
                    
                    let image = ahfail_ui::display::place_sprite(
                        &data.fixed, animation, screen_w, screen_h, &state.config
                    );
                    data.sprites.push(image);

                    let player = if let Some(p) = data.ready_players.pop() {
                        p
                    } else {
                        ahfail_ui::audio::create_player(audio_uri)
                    };

                    player.play();
                    data.active_players.push(player);

                    let new_player = ahfail_ui::audio::create_player(audio_uri);
                    data.ready_players.push(new_player);
                }
            });

            std::thread::spawn(|| {
                ahfail_ui::update::check_for_update(ahfail_ui::VERSION);
            });
        });

        unsafe {
            (*ctx.get_data_ptr()).signal_id = Some(signal_id);
        }
    }

    pub unsafe fn destroy(ctx: &WindowContext) {
        if let Some(data) = ctx.take_data() {
            if let Some(signal_id) = data.signal_id {
                let error_label = ctx.get_error_label();
                error_label.disconnect(signal_id);
            }

            for sprite in data.sprites {
                sprite.destroy();
            }
            for player in data.active_players {
                player.stop();
            }
            for player in data.ready_players {
                player.stop();
            }
            data.fixed.destroy();
        }
    }

}

