use crate::core::color::RGBToSpectrumTableData;
use bytemuck::cast_slice;
use once_cell::sync::Lazy;
use shared::Float;
use shared::PBRTOptions;
use std::sync::OnceLock;

static OPTIONS: OnceLock<PBRTOptions> = OnceLock::new();

pub fn init_pbrt(options: PBRTOptions) {
    OPTIONS
        .set(options)
        .expect("PBRT has already been initialized!");
}

pub fn get_options() -> &'static PBRTOptions {
    OPTIONS.get().unwrap_or_else(|| {
        static DEFAULT: OnceLock<PBRTOptions> = OnceLock::new();
        DEFAULT.get_or_init(PBRTOptions::default)
    })
}

static SRGB_SCALE_BYTES: &[u8] = include_bytes!("../data/srgb_scale.dat");
static SRGB_COEFFS_BYTES: &[u8] = include_bytes!("../data/srgb_coeffs.dat");

pub static SRGB_SCALE: Lazy<&[Float]> = Lazy::new(|| cast_slice(SRGB_SCALE_BYTES));

pub static SRGB_COEFFS: Lazy<&[Float]> =
    Lazy::new(|| match bytemuck::try_cast_slice(SRGB_COEFFS_BYTES) {
        Ok(s) => s,
        Err(_) => {
            let v: Vec<Float> = bytemuck::pod_collect_to_vec(SRGB_COEFFS_BYTES);
            Box::leak(v.into_boxed_slice())
        }
    });

static DCI_P3_SCALE_BYTES: &[u8] = include_bytes!("../data/dcip3_scale.dat");
static DCI_P3_COEFFS_BYTES: &[u8] = include_bytes!("../data/dcip3_coeffs.dat");
pub static DCI_P3_SCALE: Lazy<&[Float]> = Lazy::new(|| cast_slice(DCI_P3_SCALE_BYTES));
pub static DCI_P3_COEFFS: Lazy<&[Float]> =
    Lazy::new(|| match bytemuck::try_cast_slice(DCI_P3_COEFFS_BYTES) {
        Ok(s) => s,
        Err(_) => {
            let v: Vec<Float> = bytemuck::pod_collect_to_vec(DCI_P3_COEFFS_BYTES);
            Box::leak(v.into_boxed_slice())
        }
    });

static ACES_SCALE_BYTES: &[u8] = include_bytes!("../data/aces_scale.dat");
static ACES_COEFFS_BYTES: &[u8] = include_bytes!("../data/aces_coeffs.dat");

pub static ACES_SCALE: Lazy<&[Float]> = Lazy::new(|| cast_slice(ACES_SCALE_BYTES));

pub static ACES_COEFFS: Lazy<&[Float]> =
    Lazy::new(|| match bytemuck::try_cast_slice(ACES_COEFFS_BYTES) {
        Ok(s) => s,
        Err(_) => {
            let v: Vec<Float> = bytemuck::pod_collect_to_vec(ACES_COEFFS_BYTES);
            Box::leak(v.into_boxed_slice())
        }
    });

static REC2020_SCALE_BYTES: &[u8] = include_bytes!("../data/rec2020_scale.dat");
static REC2020_COEFFS_BYTES: &[u8] = include_bytes!("../data/rec2020_coeffs.dat");

pub static REC2020_SCALE: Lazy<&[Float]> = Lazy::new(|| cast_slice(REC2020_SCALE_BYTES));
pub static REC2020_COEFFS: Lazy<&[Float]> =
    Lazy::new(|| match bytemuck::try_cast_slice(REC2020_COEFFS_BYTES) {
        Ok(s) => s,
        Err(_) => {
            let v: Vec<Float> = bytemuck::pod_collect_to_vec(REC2020_COEFFS_BYTES);
            Box::leak(v.into_boxed_slice())
        }
    });

pub static SRGB_TABLE: Lazy<RGBToSpectrumTableData> =
    Lazy::new(|| RGBToSpectrumTableData::new(SRGB_SCALE.to_vec(), SRGB_COEFFS.to_vec()));

pub static DCI_P3_TABLE: Lazy<RGBToSpectrumTableData> =
    Lazy::new(|| RGBToSpectrumTableData::new(DCI_P3_SCALE.to_vec(), DCI_P3_COEFFS.to_vec()));

pub static REC2020_TABLE: Lazy<RGBToSpectrumTableData> =
    Lazy::new(|| RGBToSpectrumTableData::new(REC2020_SCALE.to_vec(), REC2020_COEFFS.to_vec()));

pub static ACES_TABLE: Lazy<RGBToSpectrumTableData> =
    Lazy::new(|| RGBToSpectrumTableData::new(ACES_SCALE.to_vec(), ACES_COEFFS.to_vec()));

// pub static ACES_TABLE: Lazy<RGBToSpectrumTableData> = Lazy::new(|| {
//     RGBToSpectrumTableData::load(Path::new("data/"), "aces2065_1")
//         .expect("Failed to load ACES table")
// });
