use crate::WADFile;

use std::sync::OnceLock;

static WAD_INSTANCE: OnceLock<WADFile> = OnceLock::new();

/// Helper function to access the WAD file once
fn get_wad() -> &'static WADFile {
    WAD_INSTANCE.get_or_init(|| WADFile::new(String::from("WADs/doom1.wad")))
}

#[test]
pub fn successful_wad_id() {
    let wad_file = get_wad();

    assert_eq!(wad_file.wad_id, "IWAD");
}

#[test]
pub fn correct_lumps() {
    let wad_file = get_wad();

    assert_eq!(wad_file.num_lumps, 1264);
}

#[test]
pub fn correct_dir_size() {
    let wad_file = get_wad();

    assert_eq!(wad_file.directory.len(), 1264);
}

#[test]
pub fn correct_lump_name() {
    let wad_file = get_wad();

    assert_eq!(wad_file.directory[0].name, "PLAYPAL");
}

#[test]
pub fn read_level_lump() {
    let wad_file = get_wad();

    assert_eq!(wad_file.directory[6].name, "E1M1");
}

#[test]
pub fn read_vertex_lump() {
    let wad_file = get_wad();

    let vertex_lump = wad_file.get_vertex_lump(&wad_file.directory[10]);

    assert_ne!(vertex_lump.vertexes.len(), 0);
}

#[test]
pub fn read_num_vertexes() {
    let wad_file = get_wad();

    let vertex_lump = wad_file.get_vertex_lump(&wad_file.directory[10]);

    assert_eq!(vertex_lump.vertexes.len(), 1868 / 4);
}

#[test]
pub fn read_first_vertex() {
    use crate::types::Vertex;

    let wad_file = get_wad();

    let vertex_lump = wad_file.get_vertex_lump(&wad_file.directory[10]);

    let correct_vertex = Vertex { x: 1088, y: -3680 };

    assert_eq!(vertex_lump.get_vertex(0), correct_vertex);
}

#[test]
pub fn get_num_vertex_lumps() {
    use crate::lumps::{Lump, LumpType};

    let mut vetex_lumps: Vec<Lump> = Vec::new();

    let wad_file = get_wad();

    for entry in 0..wad_file.num_lumps as usize {
        if let LumpType::Vertex = wad_file.directory[entry].lump_type {
            vetex_lumps.push(wad_file.directory[entry].to_owned());
        }
    }

    assert_eq!(vetex_lumps.len(), 9);
}

#[test]
pub fn get_num_vertexes() {
    let wad_file = get_wad();

    let vertex_lump = wad_file.get_vertex_lump(&wad_file.directory[10]);

    assert_eq!(vertex_lump.get_num_vertexes(), 467);
}

#[test]
pub fn read_first_linedef() {
    use crate::types::Linedef;

    let wad_file = get_wad();

    let linedef_lump = wad_file.get_linedef_lump(&wad_file.directory[8]);

    let correct_linedef = Linedef {
        vertex1: 0,
        vertex2: 1,
        flags: 1,
        special: 0,
        tag: 0,
        front_sidedef: 0,
        back_sidedef: -1,
    };

    assert_eq!(linedef_lump.get_linedef(0), correct_linedef);
}

#[test]
pub fn get_num_linedef_lumps() {
    use crate::lumps::{Lump, LumpType};

    let mut linedef_lumps: Vec<Lump> = Vec::new();

    let wad_file = get_wad();

    for entry in 0..wad_file.num_lumps as usize {
        if let LumpType::Linedef = wad_file.directory[entry].lump_type {
            linedef_lumps.push(wad_file.directory[entry].to_owned());
        }
    }

    assert_eq!(linedef_lumps.len(), 9);
}

#[test]
pub fn get_num_linedefs() {
    let wad_file = get_wad();

    let linedef_lump = wad_file.get_linedef_lump(&wad_file.directory[8]);

    assert_eq!(linedef_lump.get_num_linedefs(), 475);
}

#[test]
pub fn read_first_sidedef() {
    use crate::types::Sidedef;

    let wad_file = get_wad();

    let sidedef_lump = wad_file.get_sidedef_lump(&wad_file.directory[9]);

    let correct_sidedef = Sidedef {
        x_offset: 0,
        y_offset: 0,
        upper_texture: String::from("-"),
        lower_texture: String::from("-"),
        middle_texture: String::from("DOOR3"),
        sector: 40,
    };

    assert_eq!(sidedef_lump.get_sidedef(0), correct_sidedef);
}

#[test]
pub fn get_num_sidedef_lumps() {
    use crate::lumps::{Lump, LumpType};

    let mut sidedef_lumps: Vec<Lump> = Vec::new();

    let wad_file = get_wad();

    for entry in 0..wad_file.num_lumps as usize {
        if let LumpType::Sidedef = wad_file.directory[entry].lump_type {
            sidedef_lumps.push(wad_file.directory[entry].to_owned());
        }
    }

    assert_eq!(sidedef_lumps.len(), 9);
}

#[test]
pub fn get_num_sidedefs() {
    let wad_file = get_wad();

    let sidedef_lump = wad_file.get_sidedef_lump(&wad_file.directory[9]);

    assert_eq!(sidedef_lump.get_num_sidedefs(), 648);
}

#[test]
pub fn read_first_thing() {
    use crate::types::Thing;

    let wad_file = get_wad();

    let thing_lump = wad_file.get_thing_lump(&wad_file.directory[7]);

    let correct_thing = Thing {
        x_position: 1056,
        y_position: -3616,
        angle: 90,
        thing_type: 1,
        flags: 7,
    };

    assert_eq!(thing_lump.get_thing(0), correct_thing);
}

#[test]
pub fn get_num_thing_lumps() {
    use crate::lumps::{Lump, LumpType};

    let mut thing_lumps: Vec<Lump> = Vec::new();

    let wad_file = get_wad();

    for entry in 0..wad_file.num_lumps as usize {
        if let LumpType::Thing = wad_file.directory[entry].lump_type {
            thing_lumps.push(wad_file.directory[entry].to_owned());
        }
    }

    assert_eq!(thing_lumps.len(), 9);
}

#[test]
pub fn get_num_things() {
    let wad_file = get_wad();

    let thing_lump = wad_file.get_thing_lump(&wad_file.directory[7]);

    assert_eq!(thing_lump.get_num_things(), 138);
}

#[test]
pub fn read_first_seg() {
    use crate::types::Seg;

    let wad_file = get_wad();

    let seg_lump = wad_file.get_seg_lump(&wad_file.directory[11]);

    let correct_seg = Seg {
        start_vertex: 123,
        end_vertex: 124,
        angle: 16384,
        linedef: 152,
        direction: 0,
        offset: 0,
    };

    assert_eq!(seg_lump.get_seg(0), correct_seg);
}

#[test]
pub fn get_num_seg_lumps() {
    use crate::lumps::{Lump, LumpType};

    let mut seg_lumps: Vec<Lump> = Vec::new();

    let wad_file = get_wad();

    for entry in 0..wad_file.num_lumps as usize {
        if let LumpType::Seg = wad_file.directory[entry].lump_type {
            seg_lumps.push(wad_file.directory[entry].to_owned());
        }
    }

    assert_eq!(seg_lumps.len(), 9);
}

#[test]
pub fn get_num_segs() {
    let wad_file = get_wad();

    let thing_lump = wad_file.get_seg_lump(&wad_file.directory[11]);

    assert_eq!(thing_lump.get_num_segs(), 732);
}
