use crate::theme::Theme;
use crate::ui::dialog_search::SearchFilters;
pub use crate::ui::menu::{MenuAction, MenuState};
use crate::ui::widget::Widget;
use image::DynamicImage;
use ratatui::widgets::ListState;
use ratatui_image::picker::Picker;
use std::collections::HashMap;
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActivePane {
    Disassembly,
    HexDump,
    Sprites,
    Charset,
    Bitmap,
    Blocks,
    Debugger,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NavigationTarget {
    Index(usize),
    Address(u16),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum RightPane {
    None,
    #[default]
    HexDump,
    Sprites,
    Charset,
    Bitmap,
    Blocks,
    Debugger,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScreenRamMode {
    AfterBitmap,
    BankOffset(u8), // 0-15
}

use crate::state::HexdumpViewMode;

pub struct UIState {
    pub active_dialog: Option<Box<dyn Widget>>,
    pub file_dialog_current_dir: PathBuf,

    pub menu: MenuState,

    pub navigation_history: Vec<(ActivePane, NavigationTarget)>,
    #[allow(dead_code)]
    pub disassembly_state: ListState,

    // UI Selection/Cursor
    pub selection_start: Option<usize>,
    pub cursor_index: usize,
    pub sub_cursor_index: usize,
    pub scroll_index: usize,
    pub scroll_sub_index: usize,

    // Hex View State
    pub hex_cursor_index: usize,
    pub hex_col_cursor: usize,
    pub hex_selection_start: Option<usize>,
    pub hex_selection_start_col: usize,
    pub sprites_cursor_index: usize,
    pub sprites_selection_start: Option<usize>,
    pub charset_cursor_index: usize,
    pub charset_selection_start: Option<usize>,
    pub bitmap_cursor_index: usize,

    pub blocks_list_state: ListState,
    pub bookmarks_list_state: ListState,
    pub recent_list_state: ListState,
    #[allow(dead_code)]
    pub hex_scroll_index: usize,
    pub right_pane: RightPane,
    pub sprite_multicolor_mode: bool,
    pub charset_multicolor_mode: bool,
    pub bitmap_multicolor_mode: bool,
    pub bitmap_screen_ram_mode: ScreenRamMode,
    pub hexdump_view_mode: HexdumpViewMode,

    pub active_pane: ActivePane,
    pub should_quit: bool,
    pub status_bar: crate::ui::statusbar::StatusBarState,

    pub logo: Option<DynamicImage>,
    pub picker: Option<Picker>,
    pub dismiss_logo: bool,
    pub is_visual_mode: bool,
    pub input_buffer: String,

    pub theme: Theme,

    // Vim-like search
    pub vim_search_active: bool,
    pub vim_search_input: String,
    pub last_search_query: String,
    pub search_filters: SearchFilters,

    // Bitmap cache: key is (bitmap_address, multicolor_mode, screen_ram_address)
    pub bitmap_cache: HashMap<(usize, bool, usize), DynamicImage>,

    // Version update notification
    pub new_version_available: Option<String>,

    // Layout Areas for Mouse Interaction
    pub menu_area: ratatui::layout::Rect,
    pub main_area: ratatui::layout::Rect,
    pub status_bar_area: ratatui::layout::Rect,
    pub disassembly_area: ratatui::layout::Rect,
    pub right_pane_area: ratatui::layout::Rect,
    pub active_dialog_area: ratatui::layout::Rect,
}

impl UIState {
    pub fn new(theme: Theme) -> Self {
        Self {
            active_dialog: None,
            file_dialog_current_dir: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),

            menu: MenuState::new(),
            navigation_history: Vec::new(),
            disassembly_state: ListState::default(),
            selection_start: None,
            cursor_index: 0,
            sub_cursor_index: 0,
            scroll_index: 0,
            scroll_sub_index: 0,
            hex_cursor_index: 0,
            hex_col_cursor: 0,
            hex_selection_start: None,
            hex_selection_start_col: 0,
            sprites_cursor_index: 0,
            sprites_selection_start: None,
            charset_cursor_index: 0,
            charset_selection_start: None,
            bitmap_cursor_index: 0,
            blocks_list_state: ListState::default(),
            bookmarks_list_state: ListState::default(),
            recent_list_state: ListState::default(),
            hex_scroll_index: 0,
            right_pane: RightPane::HexDump,
            sprite_multicolor_mode: false,
            charset_multicolor_mode: false,
            bitmap_multicolor_mode: false,
            bitmap_screen_ram_mode: ScreenRamMode::AfterBitmap,
            hexdump_view_mode: HexdumpViewMode::ScreencodeShifted,
            active_pane: ActivePane::Disassembly,
            should_quit: false,
            status_bar: crate::ui::statusbar::StatusBarState::new(),
            logo: crate::utils::load_logo(),
            picker: crate::utils::create_picker(),
            dismiss_logo: false,
            is_visual_mode: false,
            input_buffer: String::new(),
            vim_search_active: false,
            vim_search_input: String::new(),
            last_search_query: String::new(),
            search_filters: SearchFilters::default(),
            bitmap_cache: HashMap::new(),
            theme,

            new_version_available: None,

            menu_area: ratatui::layout::Rect::default(),
            main_area: ratatui::layout::Rect::default(),
            status_bar_area: ratatui::layout::Rect::default(),
            disassembly_area: ratatui::layout::Rect::default(),
            right_pane_area: ratatui::layout::Rect::default(),
            active_dialog_area: ratatui::layout::Rect::default(),
        }
    }

    pub fn set_status_message(&mut self, message: impl Into<String>) {
        self.status_bar.set_message(message);
    }

    pub fn restore_session(
        &mut self,
        loaded_data: &crate::state::LoadedProjectData,
        app_state: &crate::state::AppState,
    ) {
        let loaded_cursor = loaded_data.cursor_address;
        let loaded_hex_cursor = loaded_data.hex_dump_cursor_address;
        let loaded_sprites_cursor = loaded_data.sprites_cursor_address;
        let loaded_right_pane = &loaded_data.right_pane_visible;
        let loaded_charset_cursor = loaded_data.charset_cursor_address;

        self.sprite_multicolor_mode = loaded_data.sprite_multicolor_mode;
        self.charset_multicolor_mode = loaded_data.charset_multicolor_mode;
        self.bitmap_multicolor_mode = loaded_data.bitmap_multicolor_mode.unwrap_or(false);
        self.hexdump_view_mode = loaded_data.hexdump_view_mode;
        let initial_addr = loaded_cursor.unwrap_or(app_state.origin);
        if let Some(idx) = app_state.get_line_index_for_address(initial_addr) {
            self.cursor_index = idx;
            // Also reset scroll and sub-cursor so it's visible at top
            self.scroll_index = idx;
            self.sub_cursor_index = 0;
            self.scroll_sub_index = 0;
        }

        // Update file dialog directory to the project/file location
        if let Some(path) = &app_state.project_path {
            if let Some(parent) = path.parent() {
                self.file_dialog_current_dir = parent.to_path_buf();
            }
        } else if let Some(path) = &app_state.file_path
            && let Some(parent) = path.parent()
        {
            self.file_dialog_current_dir = parent.to_path_buf();
        }

        // Also restore hex cursor if present
        if let Some(hex_addr) = loaded_hex_cursor
            && !app_state.raw_data.is_empty()
        {
            let origin = app_state.origin as usize;
            let alignment_padding = origin % 16;
            let aligned_origin = origin - alignment_padding;
            let target = hex_addr as usize;

            if target >= aligned_origin {
                let offset = target - aligned_origin;
                let row = offset / 16;
                // Ensure row is within bounds
                let total_len = app_state.raw_data.len() + alignment_padding;
                let max_rows = total_len.div_ceil(16);
                if row < max_rows {
                    self.hex_cursor_index = row;
                }
            }
        }

        // Restore Right Pane and Sprites Cursor
        if let Some(pane_str) = loaded_right_pane {
            match pane_str.as_str() {
                "HexDump" => self.right_pane = RightPane::HexDump,
                "None" => self.right_pane = RightPane::None,
                "Sprites" => self.right_pane = RightPane::Sprites,
                "Charset" => self.right_pane = RightPane::Charset,
                "Bitmap" => self.right_pane = RightPane::Bitmap,
                "Blocks" => self.right_pane = RightPane::Blocks,
                _ => {}
            }
        }
        if let Some(idx) = loaded_data.blocks_view_cursor {
            self.blocks_list_state.select(Some(idx));
        }
        if let Some(sprites_addr) = loaded_sprites_cursor {
            let origin = app_state.origin as usize;
            let aligned_origin = (origin / 64) * 64;
            let addr = sprites_addr as usize;
            if addr >= aligned_origin {
                let offset = addr - aligned_origin;
                self.sprites_cursor_index = offset / 64;
            }
        }
        if let Some(charset_addr) = loaded_charset_cursor {
            let origin = app_state.origin as usize;
            let base_alignment = 0x400;
            let aligned_start_addr = (origin / base_alignment) * base_alignment;
            let addr = charset_addr as usize;
            if addr >= aligned_start_addr {
                let offset = addr - aligned_start_addr;
                self.charset_cursor_index = offset / 8;
            }
        }

        // Restore Bitmap Cursor
        if let Some(bitmap_addr) = loaded_data.bitmap_cursor_address {
            let origin = app_state.origin as usize;
            // Bitmaps must be aligned to 8192-byte boundaries
            let aligned_start_addr = (origin / 8192) * 8192;
            let addr = bitmap_addr as usize;
            if addr >= aligned_start_addr {
                let offset = addr - aligned_start_addr;
                self.bitmap_cursor_index = offset / 8192;
            }
        }
    }
}
