use std::{path::PathBuf, process};

use crate::types::{
    class::Class,
    config::GradesConfigFile,
    data::GradesDataFile,
    grade_type::{GradeType, GradeTypeGroup, GradeTypeName},
};

pub mod add;
pub mod list;

pub fn deserialize_config_and_data(
    raw_data_file: &PathBuf,
    raw_config_file: &PathBuf,
) -> (GradesDataFile, GradesConfigFile) {
    let data_file: GradesDataFile = match GradesDataFile::from_ron_file(raw_data_file) {
        Ok(output) => output,
        Err(e) => {
            eprintln!("Error whilst reading data file: {e}");
            process::exit(1);
        }
    };
    let config_file: GradesConfigFile = match GradesConfigFile::from_yaml_file(raw_config_file) {
        Ok(output) => output,
        Err(e) => {
            eprintln!("Error whilst reading config file: {e}");
            process::exit(1);
        }
    };
    (data_file, config_file)
}

pub fn turn_string_to_grade_type(grade_type: &String, config_file: &GradesConfigFile) -> GradeType {
    let grade_type: GradeType = match config_file
        .grade_types
        .iter()
        .filter(|input_grade_type| input_grade_type.name.to_string() == *grade_type)
        .last()
    {
        Some(grade_type) => grade_type.to_owned(),
        None => {
            eprintln!(
                "No grade_type matches your specified grade_type. Did you declare it in the config file?"
            );
            process::exit(1);
        }
    };
    grade_type
}

pub fn turn_string_to_grade_type_group(
    grade_type_group: &String,
    config_file: &GradesConfigFile,
) -> GradeTypeGroup {
    let grade_type: GradeTypeGroup = match config_file
        .grade_groups
        .iter()
        .filter(|input_grade_type| input_grade_type.name.to_string() == *grade_type_group)
        .last()
    {
        Some(grade_type) => grade_type.to_owned(),
        None => {
            eprintln!(
                "No grade_type matches your specified grade_type. Did you declare it in the config file?"
            );
            process::exit(1);
        }
    };
    grade_type
}

pub fn turn_string_to_class(class: &String, config_file: &GradesConfigFile) -> Class {
    let class: Class = match config_file
        .classes
        .iter()
        .filter(|input_class| input_class.name.to_string() == *class)
        .last()
    {
        Some(class) => class.to_owned(),
        None => {
            eprintln!(
                "No class matches your specified class. Did you declare it in the config file?"
            );
            process::exit(1);
        }
    };
    class
}
pub fn turn_grade_type_name_to_grade_type(
    grade_type_name: &GradeTypeName,
    config_file: &GradesConfigFile,
) -> GradeType {
    turn_string_to_grade_type(&grade_type_name.0, config_file)
}
