use crate::sketchbook::data_structs::ObservationData;
use crate::sketchbook::ids::DatasetId;
use crate::sketchbook::observations::{Dataset, Observation};
use crate::sketchbook::JsonSerde;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct DatasetData {
    pub name: String,
    pub id: String,
    pub annotation: String,
    pub observations: Vec<ObservationData>,
    pub variables: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct DatasetMetaData {
    pub name: String,
    pub id: String,
    pub annotation: String,
    pub variables: Vec<String>,
}
impl<'de> JsonSerde<'de> for DatasetData {}
impl<'de> JsonSerde<'de> for DatasetMetaData {}
impl DatasetData {
    pub fn from_dataset(id: &DatasetId, dataset: &Dataset) -> DatasetData {
        let observations = dataset
            .observations()
            .iter()
            .map(|o| ObservationData::from_obs(o, id))
            .collect();
        let variables = dataset.variables().iter().map(|v| v.to_string()).collect();
        let annotation = dataset.get_annotation().to_string();
        let name = dataset.get_name().to_string();
        DatasetData {
            name,
            id: id.to_string(),
            annotation,
            observations,
            variables,
        }
    }
    pub fn to_dataset(&self) -> Result<Dataset, String> {
        let observations = self
            .observations
            .iter()
            .map(|o| o.to_observation())
            .collect::<Result<Vec<Observation>, String>>()?;
        let variables = self.variables.iter().map(|v| v.as_str()).collect();
        Dataset::new_annotated(&self.name, &self.annotation, observations, variables)
    }
}
impl DatasetMetaData {
    pub fn from_dataset(id: &DatasetId, dataset: &Dataset) -> DatasetMetaData {
        let variables = dataset.variables().iter().map(|v| v.to_string()).collect();
        DatasetMetaData {
            name: dataset.get_name().to_string(),
            id: id.to_string(),
            annotation: dataset.get_annotation().to_string(),
            variables,
        }
    }
}
#[cfg(test)]
mod tests {
    use crate::sketchbook::data_structs::DatasetData;
    use crate::sketchbook::ids::DatasetId;
    use crate::sketchbook::observations::{Dataset, Observation};
    #[test]
    fn test_converting() {
        let dataset_id = DatasetId::new("d").unwrap();
        let obs1 = Observation::try_from_str("*1", "o1").unwrap();
        let obs2 = Observation::try_from_str("00", "o2").unwrap();
        let dataset_before = Dataset::new("d", vec![obs1, obs2], vec!["a", "b"]).unwrap();
        let dataset_data = DatasetData::from_dataset(&dataset_id, &dataset_before);
        let dataset_after = dataset_data.to_dataset().unwrap();
        assert_eq!(dataset_before, dataset_after);
    }
}