use std::{convert::TryInto, io::Read};

use vulkano::{format::Format, sampler::{Filter, SamplerAddressMode}};

use super::{Texture, VulkanRenderer};

pub fn upload_texture_from_file(path: &str, renderer: &mut VulkanRenderer) -> Result<Texture, Box<dyn std::error::Error>> {
    // Load file
    let mut tex_file = std::fs::File::open(path)?;
    let mut tex_bytes: Vec<u8> = vec![];
    tex_file.read_to_end(&mut tex_bytes)?;

    // Parse DDS
    let tex_height = u32::from_ne_bytes(tex_bytes[12..16].try_into()?);
    let tex_width = u32::from_ne_bytes(tex_bytes[16..20].try_into()?);
    let tex_byte_count = u32::from_ne_bytes(tex_bytes[20..24].try_into()?);
    let pixel_format_flags = u32::from_ne_bytes(tex_bytes[80..84].try_into()?);
    let pixel_format_name: [u8; 4] = tex_bytes[84..88].try_into()?;
    let is_dxt1 = pixel_format_name == [0x44, 0x58, 0x54, 0x31]; // [D,X,T,1]
    let is_dx10 = pixel_format_name == [0x44, 0x58, 0x31, 0x30]; // [D,X,1,0]

    assert!(pixel_format_flags == 0x00000004);
    assert!(is_dxt1 || is_dx10);

    println!("Texture width: {}, height: {}, bytes: {}", tex_width, tex_height, tex_byte_count);

    let texture = if is_dxt1 {
        renderer.upload_texture(&tex_bytes[128..], tex_width, tex_height, Format::BC1_RGB_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone())
    } else if is_dx10 {
        let dxgi_type = u32::from_ne_bytes(tex_bytes[128..132].try_into()?);
        assert!(dxgi_type == 83); // BC5 Unorm Typeless
        
        renderer.upload_texture(&tex_bytes[128+20..], tex_width, tex_height, Format::BC5_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone())
    } else {
        panic!("Unknown texture type!");
    };

    Ok(texture)
}

pub fn get_block_size(format: Format) -> Option<u32> {
    match format {
        Format::BC1_RGB_UNORM_BLOCK => Some(8),
        Format::BC5_UNORM_BLOCK => Some(16),
        _ => None
    }
}