// Menu Widget stuff i.e episode selection etc.

// TODO: Implement d_event.handle

use std::ptr::addr_of_mut;

use crate::doomdef::{DOOMGLOBALS, GameMode};

#[repr(C)]
#[derive(Copy, Clone)]
#[allow(non_snake_case)]
struct menuitem_t {
    status: i32,
    name: [u8; 10],
    routine: Option<fn(choice: i32)>,
    
    // hotkey in menu
    alpha_key: u8,
}

#[repr(C)]
#[derive(Copy, Clone)]
#[allow(non_snake_case)]
struct menu_t {
    
    /// Number of items in the menu
    numitems: i32,

    /// Pointer to the previous menu
    prevMenu: *mut menu_t,

    /// The menu items
    menuItems: *mut menuitem_t,

    /// draw routine
    routine: Option<fn()>,

    /// X of the menu
    x: i32,

    /// y of the menu
    y: i32,

    /// The last item the user was on in the menu
    lastOn: i32
}

/// TEMP function
#[allow(non_snake_case)]
fn VoidRoutine() {

}

#[allow(non_snake_case)]
fn VoidRoutineWithChoice(choice: i32) {
    let _ = choice;
}


// Main Menu
#[allow(non_snake_case)]
mod MainMenu {
    use super::*;

    /// Enumeration of the main menu options
    #[allow(non_camel_case_types)]
    pub(super) enum main_e {
        newgame = 0,
        options,
        loadgame,
        savegame,
        readthis,
        quitdoom,
        main_end
    }

    /// Main Menu items
    #[allow(non_upper_case_globals)]
    pub(super) static mut MainMenu: [menuitem_t; 6] = [
        menuitem_t {
            status: 1,
            name: *b"M_NGAME\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'n'
        },
        menuitem_t {
            status: 1,
            name: *b"M_OPTION\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'o'
        },
        menuitem_t {
            status: 1,
            name: *b"M_LOADG\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'l'
        },
        menuitem_t {
            status: 1,
            name: *b"M_SAVEG\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b's'
        },
        menuitem_t {
            status: 1,
            name: *b"M_RDTHIS\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'r'
        },
        menuitem_t {
            status: 1,
            name: *b"M_QUITG\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'q'
        }    
    ];

    /// Default MainMenu
    #[allow(non_upper_case_globals)]
    pub(super) static mut MainDef: menu_t = menu_t {
        numitems: main_e::main_end as i32,
        prevMenu: std::ptr::null_mut(),
        menuItems: &raw mut MainMenu as *mut menuitem_t, // Use &raw mut instead of .as_mut_ptr() to avoid illegal static mut references (Feels dirty)
        routine: Some(VoidRoutine),
        x: 97,
        y: 64,
        lastOn: 0,
    };
}

// New Game menu
#[allow(non_snake_case)]
mod NewGameMenu {
    use super::*;

    /// Enumeration of the New Game options
    #[allow(non_camel_case_types)]
    pub(super) enum newgame_e {
        killthings,
        toorough,
        hurtme,
        violence,
        nightmare,
        newg_end
    }

    /// New Game Menu items
    #[allow(non_upper_case_globals)]
    pub(super) static mut NewGameMenu: [menuitem_t; 5] = [
        menuitem_t {
            status: 1,
            name: *b"M_JKILL\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'i'
        },
        menuitem_t {
            status: 1,
            name: *b"M_ROUGH\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'h'
        },
        menuitem_t {
            status: 1,
            name: *b"M_HURT\0\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'h'
        },
        menuitem_t {
            status: 1,
            name: *b"M_ULTRA\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'u'
        },
        menuitem_t {
            status: 1,
            name: *b"M_NMARE\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'n'
        }
    ];

    #[allow(non_upper_case_globals)]
    pub(super) static mut NewDef: menu_t = menu_t {
        numitems: newgame_e::newg_end as i32,
        prevMenu: std::ptr::null_mut(), // TODO: Add EpiDef
        menuItems: &raw mut NewGameMenu as *mut menuitem_t, // Use &raw mut instead of .as_mut_ptr() to avoid illegal static mut references (Feels dirty)
        routine: Some(VoidRoutine),
        x: 48,
        y: 63,
        lastOn: newgame_e::hurtme as i32,
    };
}

// TODO: add OptionsMenu
#[allow(non_snake_case)]
mod ReadThis1 {
    use super::*;

    /// Enumeration of the main menu options
    #[allow(non_camel_case_types)]
    pub(super) enum read_e {
        rdthisempty1 = 0,
        read1_end,
    }

    /// Read1 Menu items
    #[allow(non_upper_case_globals)]
    pub(super) static mut ReadMenu1: [menuitem_t; 1] = [
        menuitem_t {
            status: 1,
            name: *b"\0\0\0\0\0\0\0\0\0\0",
            routine: Some(VoidRoutineWithChoice),
            alpha_key: b'0'
        }
    ];

    /// Default MainMenu
    #[allow(non_upper_case_globals)]
    pub(super) static mut Read1Def: menu_t = menu_t {
        numitems: read_e::rdthisempty1 as i32,
        prevMenu: addr_of_mut!(MainMenu::MainDef),
        menuItems: &raw mut ReadMenu1 as *mut menuitem_t, // Use &raw mut instead of .as_mut_ptr() to avoid illegal static mut references (Feels dirty)
        routine: Some(VoidRoutine),
        x: 280,
        y: 185,
        lastOn: 0,
    };
}

// TODO: The rest of this hell!

#[allow(non_upper_case_globals)]
static mut currentMenu: *mut menu_t = std::ptr::null_mut();

#[allow(non_upper_case_globals)]
static mut menuactive: bool = false;

#[allow(non_upper_case_globals)]
static mut itemOn: i32 = 0;

#[allow(non_upper_case_globals)]
static mut whichSkull: i32 = 0;

#[allow(non_upper_case_globals)]
static mut skullAnimCounter: i32 = 0;

#[allow(non_upper_case_globals)]
pub(crate) static mut detailLevel: i32 = 0;

#[allow(non_upper_case_globals)]
pub static mut screenSize: i32 = 0;

#[allow(non_upper_case_globals)]
pub(crate) static mut screenBlocks: i32 = 0;

#[allow(non_upper_case_globals)]
static mut messageToPrint: i32 = 0;

#[allow(non_upper_case_globals)]
static mut messageString: *mut u8 = std::ptr::null_mut();

#[allow(non_upper_case_globals)]
static mut messageLastMenuActive: i32 = 0;

#[allow(non_upper_case_globals)]
static mut quickSaveSlot: i32 = -1;

#[allow(non_snake_case)]
pub fn M_Ticket() {

}

#[allow(non_snake_case)]
pub fn M_Drawer() {

}

#[allow(non_snake_case)]
pub fn M_Init() {
    unsafe {
        currentMenu = addr_of_mut!(MainMenu::MainDef);
        menuactive = false;
        itemOn = (*currentMenu).lastOn;
        whichSkull = 0;
        skullAnimCounter = 10;
        screenSize = screenBlocks - 3;
        messageToPrint = 0;
        messageString = std::ptr::null_mut();
        messageLastMenuActive = menuactive as i32;
        quickSaveSlot = -1;
    

        match DOOMGLOBALS::with_ref(|g| g.gamemode) {
            GameMode::Commercial => {
                /*
                Original source code comment:
                // This is used because DOOM 2 had only one HELP
                //  page. I use CREDIT as second page now, but
                //  kept this hack for educational purposes.
                */
                MainMenu::MainMenu[MainMenu::main_e::readthis as usize] = MainMenu::MainMenu[MainMenu::main_e::quitdoom as usize];
                MainMenu::MainDef.numitems -=1;
                MainMenu::MainDef.y += 8;
                NewGameMenu::NewDef.prevMenu = addr_of_mut!(MainMenu::MainDef);
                ReadThis1::Read1Def.routine = Some(VoidRoutine);
                ReadThis1::Read1Def.x = 330;
                ReadThis1::Read1Def.y = 165;
                ReadThis1::ReadMenu1[ReadThis1::read_e::rdthisempty1 as usize].routine = Some(VoidRoutineWithChoice);
            },
            GameMode::Shareware | GameMode::Registered => {
                // TODO EpiDef.numitems--
            }
            _ => {
                // do nothing :)
            }
        }
    }
}

#[allow(non_snake_case)]
pub fn M_StartControlPanel() {

}