use crate::gui::SoundpadGui;
use eframe::{App, Frame as EFrame};
use egui::{CentralPanel, Context, ThemePreference};
use pwsp_lib::{
    types::{config::PreferredTheme, socket::Request},
    utils::{daemon::get_daemon_config, gui::make_request_async},
};
use std::time::{Duration, Instant};

impl App for SoundpadGui {
    fn logic(&mut self, ctx: &Context, _frame: &mut EFrame) {
        // Update theme
        let current_theme = match ctx.options(|r| r.theme_preference) {
            ThemePreference::System => PreferredTheme::System,
            ThemePreference::Light => PreferredTheme::Light,
            ThemePreference::Dark => PreferredTheme::Dark,
        };

        if !self.config.preferred_theme.eq(&current_theme) {
            ctx.options_mut(|w| {
                w.theme_preference = match self.config.preferred_theme {
                    PreferredTheme::System => ThemePreference::System,
                    PreferredTheme::Light => ThemePreference::Light,
                    PreferredTheme::Dark => ThemePreference::Dark,
                }
            })
        }

        // Remove directories
        for path in self.app_state.dirs_to_remove.drain() {
            self.app_state.dirs.retain(|x| x != &path);
            if let Some(current_dir) = &self.app_state.current_dir
                && current_dir == &path
            {
                self.app_state.current_dir = None;
                self.app_state.listed_files.clear();
            }
        }

        // Save directories if changed
        if !self.config.dirs.eq(&self.app_state.dirs) {
            self.config.dirs = self.app_state.dirs.clone();
            self.config.save_to_file().ok();
        }

        // Seek and volume requests
        let mut seek_requests = vec![];
        let mut volume_requests = vec![];

        for (id, ui_state) in &mut self.app_state.track_ui_states {
            if ui_state.position_dragged {
                seek_requests.push((*id, ui_state.position_slider_value));
            }
            if ui_state.volume_dragged {
                volume_requests.push((*id, ui_state.volume_slider_value));
                ui_state.volume_dragged = false;
            }
        }

        for (id, pos) in seek_requests {
            make_request_async(Request::seek(pos, Some(id)));
            if let Some(ui_state) = self.app_state.track_ui_states.get_mut(&id) {
                ui_state.position_dragged = false;
                ui_state.ignore_position_update_until =
                    Some(Instant::now() + Duration::from_millis(300));
            }
        }

        for (id, vol) in volume_requests {
            make_request_async(Request::set_volume(vol, Some(id)));
            if let Some(ui_state) = self.app_state.track_ui_states.get_mut(&id) {
                ui_state.volume_dragged = false;
                ui_state.ignore_volume_update_until =
                    Some(Instant::now() + Duration::from_millis(300));
            }
        }

        if self.app_state.volume_dragged {
            make_request_async(Request::set_volume(
                self.app_state.volume_slider_value,
                None,
            ));

            self.app_state.volume_dragged = false;
            self.app_state.ignore_volume_update_until =
                Some(Instant::now() + Duration::from_millis(300));

            if self.config.save_volume {
                let mut daemon_config = get_daemon_config();
                daemon_config.default_volume = Some(self.app_state.volume_slider_value);
                daemon_config.save_to_file().ok();
            }
        }

        // Sync audio player state
        {
            let mut guard = self
                .audio_player_state_shared
                .lock()
                .unwrap_or_else(|e| e.into_inner());
            if let Some(config) = guard.hotkey_config.take() {
                self.app_state.hotkey_config = config;
            }
            self.audio_player_state = guard.clone();
        }

        // Handle scale factor changes
        let old_scale_factor = self.config.scale_factor;
        let new_scale_factor = ctx.zoom_factor().clamp(0.5, 2.0);

        ctx.set_zoom_factor(new_scale_factor);
        self.config.scale_factor = new_scale_factor;

        if new_scale_factor != old_scale_factor && self.config.save_scale_factor {
            self.config.save_to_file().ok();
        }

        // Handle input
        self.handle_input(ctx);
    }

    fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut EFrame) {
        // Draw UI
        CentralPanel::default().show_inside(ui, |ui| {
            if !self.audio_player_state.is_daemon_running {
                self.draw_waiting_for_daemon(ui);
                return;
            }

            if self.app_state.hotkey_capture_active {
                self.draw_hotkey_capture(ui);
                return;
            }

            if self.app_state.show_settings {
                self.draw_settings(ui);
                return;
            }

            if self.app_state.show_hotkeys {
                self.draw_hotkeys(ui);
                return;
            }

            self.draw(ui);
        });

        // Request repaint
        ui.request_repaint_after_secs(1.0 / 60.0);
    }
}
