// src/lib.rs

use serde::{Serialize, Deserialize};
use serde_json;
use std::fmt;

#[derive(Default, Serialize, Deserialize, PartialEq)]
enum Semester {
    #[default]
    Zimny,
    Letny
}

impl fmt::Display for Semester {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Semester::Zimny => write!(f, "Zimny"),
            Semester::Letny => write!(f, "Letny"),
        }
    }
}

#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Hash, Copy, Clone)]
enum TypPovinnosti {
    Povinny,
    PovinneVoliteny,
    #[default]
    Vyberovy,
}

impl fmt::Display for TypPovinnosti {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TypPovinnosti::Povinny => write!(f, "Povinny"),
            TypPovinnosti::PovinneVoliteny => write!(f, "PovinneVoliteny"),
            TypPovinnosti::Vyberovy => write!(f, "Vyberovy"),
        }
    }
}

#[derive(Default, Serialize, Deserialize)]
struct Predmet {
    kod: String,
    nazov: String,
    vyucujuci: Vec<String>,
    popis: String,
    semester: Semester,
    rocnik: u8,
    pocet_kreditov: u8,
    znamka: char,
    typ_povinnosti: TypPovinnosti
}

impl fmt::Display for Predmet {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {}, {}, {}, {}, {}, {}, {}, {})",
               self.kod,
               self.nazov,
               self.vyucujuci.join(", "),
               self.popis,
               self.semester,
               self.rocnik,
               self.pocet_kreditov,
               self.znamka,
               self.typ_povinnosti
        )
    }
}

#[derive(Default, Serialize, Deserialize)]
struct Index {
    predmety: Vec<Predmet>
}

impl Index{
    pub fn nacitaj_zo_suboru(&self, cesta: &std::path::PathBuf) -> Option<Self> {
        let data = match std::fs::read_to_string(cesta) {
            Ok(x) => x,
            Err(_) => return None,
        };
        let vysledok = match serde_json::from_str(data.as_str()) {
            Ok(k) => k,
            Err(_) => return None,
        };
        Some(vysledok)
    }

    pub fn uloz_do_suboru(&self, cesta_uloz: &std::path::PathBuf) -> bool {
        true

    }
}

impl Predmet {
    pub fn new(
        kod: String,
        nazov: String,
        vyucujuci: Vec<String>,
        popis: String,
        semester: Semester,
        rocnik: u8,
        pocet_kreditov: u8,
        znamka: char,
        typ_povinnosti: TypPovinnosti
    ) -> Self{
        return Self {
            kod: kod.to_string(),
            nazov: nazov.to_string(),
            vyucujuci,
            popis: popis.to_string(),
            semester,
            rocnik,
            pocet_kreditov,
            znamka,
            typ_povinnosti,
        }
    }
}
    // kod: &str,
    // nazov: &str,
    // vyucujuci: Vec<String>,
    // popis: &str,
    // semester: Semester,
    // rocnik: u8,
    // pocet_kreditov: u8,
    // znamka: char,
    // typ_povinnosti: TypPovinnosti
