
pub const DATA_TYPE_UINT8: u8 = 0x10;
pub const DATA_TYPE_INT16: u8 = 0x11;
pub const DATA_TYPE_UINT16: u8 = 0x12;
pub const DATA_TYPE_INT32: u8 = 0x13;
pub const DATA_TYPE_UINT32: u8 = 0x14;
pub const DATA_TYPE_FLOAT32: u8 = 0x20;
pub const DATA_TYPE_FLOAT64: u8 = 0x21;

/* 0 dn 1 rad 2 ref 3 irad 4 califile  5 flat_ref 6 dark_dn 7 flat_dn */

pub const Target_Spectral_Type_DN:u8 = 0x00;
pub const Target_Spectral_Type_Rad:u8 = 0x01;
pub const Target_Spectral_Type_Ref:u8 = 0x02;
pub const Target_Spectral_Type_IRad:u8 = 0x03;
pub const Target_Spectral_Type_CaliFile_Gain:u8 = 0x04;
pub const Target_Spectral_Type_FlatRef:u8 = 0x05;
pub const Target_Spectral_Type_DarkDN:u8 = 0x06;
pub const Target_Spectral_Type_FlatDN:u8 = 0x07;
pub const Target_LAMP_VALUE_SCALED:u8 = 0x08;

use serde::Serialize; 
use serde_json::json;



#[derive(serde::Serialize,Debug, Clone, PartialEq)]
pub struct TimeStruct {
    pub time_zone: i8,
    pub year: u16,
    pub month: u8,
    pub day: u8,
    pub hour: u8,
    pub minute: u8,
    pub second: u8,
    pub millisecond: u16,
}

impl TimeStruct {
    pub fn new() -> Self {
        TimeStruct {
            time_zone: 0,
            year: 0,
            month: 1,
            day: 1,
            hour: 0,
            minute: 0,
            second: 0,
            millisecond: 0,
        }
    }
}

#[derive(serde::Serialize,Debug, Clone, PartialEq)]
pub struct SpectralData {
    pub name: String,
    pub sensor_id: String,
    pub fiber_id: u8,
    pub collection_time: TimeStruct,
    pub exposure: f64,
    pub gain: f32,
    pub data_type: u8,
    pub pixel_size: u8,
    pub ground_type: u8,
    pub bands: u16,
    pub valid_flag: u8,
    pub spectral_data: Vec<u8>,
}

impl SpectralData {
    pub fn new() -> Self {
        SpectralData {
            name: String::new(),
            sensor_id: String::new(),
            fiber_id:0,
            collection_time: TimeStruct::new(),
            exposure: 0.0,
            gain: 0.0,
            data_type: 0,
            pixel_size: 0,
            ground_type: 0,
            bands: 0,
            valid_flag: 0,
            spectral_data: Vec::new(),
        }
    }

    pub fn Get_Spectral_Data(&self)-> Vec<f64> {
        let mut retrun_data: Vec<f64> = Vec::new();
        let datatype = self.data_type;
        let bands = self.bands as usize;
        match datatype {
            DATA_TYPE_UINT8 => {
                // uint8
                for i in 0..bands {
                    retrun_data.push(self.spectral_data[i] as f64);
                }
               
               

             
            }
            DATA_TYPE_INT16 => {
                // int16
                self.spectral_data.chunks(2).for_each(|chunk| {
                    if chunk.len() == 2 {
                        let value = i16::from_le_bytes([chunk[0], chunk[1]]);
                        retrun_data.push(value as f64);
                    }
                });
              
            }
            DATA_TYPE_UINT16 => {
                // uint16
                self.spectral_data.chunks(2).for_each(|chunk| {
                    if chunk.len() == 2 {
                        let value = u16::from_le_bytes([chunk[0], chunk[1]]);
                        retrun_data.push(value as f64);
                    }
                });
                
            }
            DATA_TYPE_INT32 => {
                // int32

                
                self.spectral_data.chunks(4).for_each(|chunk| {
                    if chunk.len() == 4 {
                        let value = i32::from_le_bytes([
                            chunk[0],
                            chunk[1],
                            chunk[2],
                            chunk[3],
                        ]);
                        retrun_data.push(value as f64);
                    }
                });
               
            }
            DATA_TYPE_UINT32 => {
                // uint32
                for i in (0..self.spectral_data.len()).step_by(4) {
                    let value = u32::from_le_bytes([
                        self.spectral_data[i],
                        self.spectral_data[i + 1],
                        self.spectral_data[i + 2],
                        self.spectral_data[i + 3],
                    ]);
                    retrun_data.push(value as f64);
                }
            }
            DATA_TYPE_FLOAT32 => {
                // float32
                for i in (0..self.spectral_data.len()).step_by(4) {
                    let value = f32::from_le_bytes([
                        self.spectral_data[i],
                        self.spectral_data[i + 1],
                        self.spectral_data[i + 2],
                        self.spectral_data[i + 3],
                    ]);
                    retrun_data.push(value as f64);
                }
            }
            DATA_TYPE_FLOAT64 => {
                // float64
                for i in (0..self.spectral_data.len()).step_by(8) {
                    let value = f64::from_le_bytes([
                        self.spectral_data[i],
                        self.spectral_data[i + 1],
                        self.spectral_data[i + 2],
                        self.spectral_data[i + 3],
                        self.spectral_data[i + 4],
                        self.spectral_data[i + 5],
                        self.spectral_data[i + 6],
                        self.spectral_data[i + 7],
                    ]);
                    retrun_data.push(value);
                }
            }
            _ => {
                // Unsupported data type
                panic!("Unsupported data type: {}", datatype);
            }
        }



        retrun_data


    }
    pub fn Set_Spectral_Data(&mut self, data: Vec<f64>,datatype: u8) {
        self.data_type = datatype;
        self.bands = data.len() as u16;
        self.spectral_data.clear();
        
       // let datatype = self.data_type;
        let bands = self.bands as usize;
        match datatype {
            DATA_TYPE_UINT8 => {
                // uint8
                self.pixel_size = 1;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        self.spectral_data.push(data[i] as u8);
                    } else {
                        self.spectral_data.push(0);
                    }
                }
            }
            DATA_TYPE_INT16 => {
                // int16
                self.pixel_size = 2;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        let value = data[i] as i16;
                        self.spectral_data.extend_from_slice(&value.to_le_bytes());
                    } else {
                        self.spectral_data.extend_from_slice(&[0, 0]);
                    }
                }
            }
            DATA_TYPE_UINT16 => {
                // uint16
                self.pixel_size = 2;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        let value = data[i] as u16;
                        self.spectral_data.extend_from_slice(&value.to_le_bytes());
                    } else {
                        self.spectral_data.extend_from_slice(&[0, 0]);
                    }
                }
            }
            DATA_TYPE_INT32 => {
                // int32
                self.pixel_size = 4;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        let value = data[i] as i32;
                        self.spectral_data.extend_from_slice(&value.to_le_bytes());
                    } else {
                        self.spectral_data.extend_from_slice(&[0, 0, 0, 0]);
                    }
                }
            }
            DATA_TYPE_UINT32 => {
                // uint32
                self.pixel_size = 4;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        let value = data[i] as u32;
                        self.spectral_data.extend_from_slice(&value.to_le_bytes());
                    } else {
                        self.spectral_data.extend_from_slice(&[0, 0, 0, 0]);
                    }
                }
            }
            DATA_TYPE_FLOAT32 => {
                // float32
                self.pixel_size = 4;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        let value = data[i] as f32;
                        self.spectral_data.extend_from_slice(&value.to_le_bytes());
                    } else {
                        self.spectral_data.extend_from_slice(&[0, 0, 0, 0]);
                    }
                }
            }
            DATA_TYPE_FLOAT64 => {
                // float64
                self.pixel_size = 8;
                self.spectral_data.clear();
                for i in 0..bands {
                    if i < data.len() {
                        let value = data[i];
                        self.spectral_data.extend_from_slice(&value.to_le_bytes());
                    } else {
                        self.spectral_data.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
                    }
                }
            }
            _ => {
                // Unsupported data type
                panic!("Unsupported data type: {}", datatype);
            }
        }

    }
}

// #[derive(Debug, Clone, PartialEq)]
// pub struct OtherInfo {
//     pub info_type: u8,
//     pub data: Vec<u8>, // Assuming the data is variable length
// }

// impl OtherInfo {
//     pub fn new() -> Self {
//         OtherInfo {
//             info_type: 0,
//             data: Vec::new(),
//         }
//     }
// }
#[derive(serde::Serialize, Debug, Clone, PartialEq)] 
pub struct OneIRISData {
    pub spectral_data_section: Vec<SpectralData>,
    pub spectral_info_section: Vec<serde_json::Value>, // Using serde_json::Value for flexibility
    pub other_info_section: Vec<serde_json::Value>,
    pub image_info_section: Vec<ImageInfo>,
}

impl OneIRISData {
    pub fn new() -> Self {
        OneIRISData {
            spectral_data_section: Vec::new(),
            spectral_info_section: Vec::new(),
            other_info_section: Vec::new(),
            image_info_section: Vec::new(),
        }
    }
}

// #[derive(Debug, Clone, PartialEq)]
// pub struct SpectralInfo {
//     pub sensor_id: String,
//     pub wave_coeff: [f64; 4],
    
// }

// impl SpectralInfo {
//     pub fn new() -> Self {
//         SpectralInfo {
//             sensor_id: String::new(),
//             wave_coeff: [0.0; 4],
//         }
//     }
// }

#[derive(serde::Serialize,Debug, Clone, PartialEq)]
pub struct ImageInfo {
    pub data_length: u64,
    pub name: String,
    pub collection_time: TimeStruct,
    pub info_type: u8,
    pub image_data: Vec<u8>, // Assuming the data is variable length
}

impl ImageInfo {
    pub fn new() -> Self {
        ImageInfo {
            data_length: 0,
            name: String::new(),
            collection_time: TimeStruct::new(),
            info_type: 0,
            image_data: Vec::new(),
        }
    }
}


#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_time_struct() {
        let time = TimeStruct::new();
        assert_eq!(time.time_zone, 0);
        assert_eq!(time.year, 0);
        assert_eq!(time.month, 1);
    }

    #[test]
    fn test_spectral_data() {
        let data = SpectralData::new();
        assert_eq!(data.name, "");
        assert_eq!(data.bands, 0);
        assert!(data.spectral_data.is_empty());
    }

    // #[test]
    // fn test_spectral_info() {
    //     let info = SpectralInfo::new();
    //     assert_eq!(info.sensor_id, "");
    //     assert_eq!(info.wave_coeff, [0.0; 4]);
    // }

    // #[test]
    // fn test_other_info() {
    //     let info = OtherInfo::new();
    //     assert_eq!(info.info_type, 0);
    //     assert!(info.data.is_empty());
    // }

    #[test]
    fn test_image_info() {
        let info = ImageInfo::new();
        assert_eq!(info.data_length, 0);
        assert_eq!(info.name, "");
        assert!(info.image_data.is_empty());
    }
}