use std::{
    collections::HashMap,
    fs::File,
    io::{Read, Write},
    sync::{Arc, OnceLock},
    thread::spawn,
};

use eframe::egui::{
    self, mutex::RwLock, vec2, Button, Color32, Frame, Label, RichText, Stroke, Vec2,
};
use egui_flex::{item, Flex, FlexInstance};
use serde::{Deserialize, Serialize};

use crate::{
    tabs::{
        activities::{
            activities, acts_frames, get_classes_name, get_teachers_name, partnered_act,
            teachers_acts_hours, Activity,
        },
        classes::{classes_acts, get_classes, selected_class},
        generating::{available_days, create_available_days, data, Schedule, TimetableData},
        get_school, school_hour,
        teachers::{get_teachers, selected_teacher, teachers_acts},
        SubPage,
    },
    DAYS,
};

use super::get_page;

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ClassLimitation {
    pub class_id: i32,
    pub limitations: Vec<Vec<bool>>,
}
impl ClassLimitation {
    pub fn new(id: i32) -> Self {
        let hour = school_hour().read().parse::<usize>().unwrap_or(8);
        Self {
            class_id: id,
            limitations: vec![vec![true; hour]; 7],
        }
    }
    fn validation(&mut self) {
        let hour = &*school_hour().read();
        let hour = hour.parse::<usize>().unwrap_or(8);
        while self.limitations.len() > 7 {
            self.limitations.pop();
        }
        while self.limitations.len() < 7 {
            self.limitations.push(vec![true; hour]);
        }
        self.limitations.iter_mut().for_each(|l| {
            while l.len() > hour {
                l.pop();
            }
            while l.len() < hour {
                l.push(true);
            }
        })
    }
}
pub fn classes_volumes() -> &'static Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>> {
    static PAGE: OnceLock<Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>>> = OnceLock::new();
    PAGE.get_or_init(|| Arc::new(RwLock::new(create_classes_volumes())))
}
fn create_classes_volumes() -> HashMap<i32, Vec<Vec<i32>>> {
    let clss = get_classes().read();
    let s_hour = get_school().read().hour;
    let acts = classes_acts().read().clone();
    let mut map = HashMap::new();
    for c in &*clss {
        let c_acts = acts.get(c.0).unwrap();
        let mut days = vec![];
        for day in DAYS.iter().enumerate() {
            let mut hours = vec![0; s_hour as usize];
            for act in c_acts {
                let h_lim = s_hour - act.hour + 1;
                for h in 0..h_lim as usize {
                    if act.hour + h <= s_hour
                        && act.classes_available(h, day.0)
                        && act.teachers_available(h, day.0)
                    {
                        (0..act.hour).for_each(|hh| hours[h + hh as usize] += 1);
                    }
                }
            }
            days.push(hours);
        }
        map.insert(*c.0 as i32, days);
    }
    map
}
pub fn teachers_volumes() -> &'static Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>> {
    static PAGE: OnceLock<Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>>> = OnceLock::new();
    PAGE.get_or_init(|| Arc::new(RwLock::new(create_teachers_volumes())))
}
fn create_teachers_volumes() -> HashMap<i32, Vec<Vec<i32>>> {
    let teachers = get_teachers().read();
    let s_hour = get_school().read().hour;
    let acts = teachers_acts().read().clone();
    let mut map = HashMap::new();
    for t in &*teachers {
        let t_acts = acts.get(t.0).unwrap();
        let mut days = vec![];
        for day in DAYS.iter().enumerate() {
            let mut hours = vec![0; s_hour as usize];
            for h in 0..s_hour as usize {
                for act in t_acts {
                    if act.hour + h <= s_hour
                        && act.classes_available(h, day.0)
                        && act.teachers_available(h, day.0)
                    {
                        hours[h] += 1;
                    }
                }
            }
            days.push(hours);
        }
        map.insert(*t.0 as i32, days);
    }
    map
}
pub fn schedules() -> &'static Arc<RwLock<Vec<Schedule>>> {
    static PAGE: OnceLock<Arc<RwLock<Vec<Schedule>>>> = OnceLock::new();
    PAGE.get_or_init(|| Arc::new(RwLock::new(vec![])))
}

pub fn classes_limitations() -> &'static Arc<RwLock<HashMap<i32, ClassLimitation>>> {
    static PAGE: OnceLock<Arc<RwLock<HashMap<i32, ClassLimitation>>>> = OnceLock::new();
    PAGE.get_or_init(|| Arc::new(RwLock::new(get_class_limitations())))
}
pub fn get_class_limitations() -> HashMap<i32, ClassLimitation> {
    let lims = File::open("./db/classes_limitations.json");
    if let Ok(mut lims) = lims {
        let mut content: String = String::new();
        lims.read_to_string(&mut content).unwrap();
        let mut cls: Vec<ClassLimitation> = serde_json::from_str(content.as_str()).unwrap();
        cls.iter_mut().for_each(|l| l.validation());
        let mut lims: HashMap<i32, ClassLimitation> = HashMap::new();
        for c in cls {
            lims.insert(c.class_id, c);
        }
        return lims;
    } else {
        let mut lims: HashMap<i32, ClassLimitation> = HashMap::new();
        for c in &*get_classes().read() {
            lims.insert(c.1.id, ClassLimitation::new(c.1.id));
        }
        return lims;
    }
}
type ClassSched = Arc<RwLock<HashMap<i32, Vec<Vec<Option<Activity>>>>>>;
pub fn classes_sched() -> &'static ClassSched {
    static ACT: OnceLock<ClassSched> = OnceLock::new();
    ACT.get_or_init(|| Arc::new(RwLock::new(create_classes_sched())))
}

fn get_class_scheds(id: i32) -> Vec<Vec<Option<Activity>>> {
    let scheds = &*classes_sched().read();
    let scheds = scheds.get(&id);
    if let Some(scheds) = scheds {
        return scheds.clone();
    } else {
        create_classes_sched();
        return get_class_scheds(id);
    }
}

fn get_class_lims(id: i32) -> Vec<Vec<bool>> {
    let lims = classes_limitations().read();
    let lims = lims.get(&id);
    if let Some(lims) = lims {
        return lims.limitations.clone();
    } else {
        std::thread::spawn(move || {
            classes_limitations()
                .write()
                .insert(id, ClassLimitation::new(id));
        });
        return get_class_lims(id);
    }
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TeacherLimitation {
    pub teacher_id: i32,
    pub limitations: Vec<Vec<bool>>,
}
impl TeacherLimitation {
    pub fn new(id: i32) -> Self {
        let hour = school_hour().read().parse::<usize>().unwrap_or(8);
        Self {
            teacher_id: id,
            limitations: vec![vec![true; hour]; 7],
        }
    }
    fn validation(&mut self) {
        let hour = &*school_hour().read();
        let hour = hour.parse::<usize>().unwrap_or(8);
        while self.limitations.len() > 7 {
            self.limitations.pop();
        }
        while self.limitations.len() < 7 {
            self.limitations.push(vec![true; hour]);
        }
        self.limitations.iter_mut().for_each(|l| {
            while l.len() > hour {
                l.pop();
            }
            while l.len() < hour {
                l.push(true);
            }
        })
    }
}

fn get_teacher_lims(id: i32) -> Vec<Vec<bool>> {
    let lims = teachers_limitations().read();
    let lims = lims.get(&id);
    if let Some(lims) = lims {
        return lims.limitations.clone();
    } else {
        let lims = TeacherLimitation::new(id);
        let lims2 = lims.clone();
        std::thread::spawn(move || {
            teachers_limitations().write().insert(id, lims2);
        });
        return lims.limitations;
    }
}
pub fn teachers_limitations() -> &'static Arc<RwLock<HashMap<i32, TeacherLimitation>>> {
    static PAGE: OnceLock<Arc<RwLock<HashMap<i32, TeacherLimitation>>>> = OnceLock::new();
    PAGE.get_or_init(|| Arc::new(RwLock::new(get_teacher_limitations())))
}

pub fn get_teacher_limitations() -> HashMap<i32, TeacherLimitation> {
    let lims = File::open("./db/teachers_limitations.json");
    if let Ok(mut lims) = lims {
        let mut content: String = String::new();
        lims.read_to_string(&mut content).unwrap();
        let mut cls: Vec<TeacherLimitation> = serde_json::from_str(content.as_str()).unwrap();
        cls.iter_mut().for_each(|l| l.validation());
        let mut lims: HashMap<i32, TeacherLimitation> = HashMap::new();
        for c in cls {
            lims.insert(c.teacher_id, c);
        }
        return lims;
    } else {
        let tchrs = get_teachers().read();
        let mut lims: HashMap<i32, TeacherLimitation> = HashMap::new();
        for t in &*tchrs {
            lims.insert(t.1.id, TeacherLimitation::new(t.1.id));
        }
        return lims;
    }
}
type TeacherSched = Arc<RwLock<HashMap<i32, Vec<Vec<Option<Activity>>>>>>;
pub fn teachers_scheds() -> &'static TeacherSched {
    // create_sched();
    static ACT: OnceLock<TeacherSched> = OnceLock::new();
    ACT.get_or_init(|| Arc::new(RwLock::new(create_teachers_sched())))
}
fn get_teacher_scheds(id: i32) -> Vec<Vec<Option<Activity>>> {
    let scheds = teachers_scheds().read();
    let scheds = scheds.get(&id);
    if let Some(scheds) = scheds {
        return scheds.clone();
    } else {
        create_teachers_sched();
        return get_teacher_scheds(id);
    }
}

fn _update_teacher_limitation() {
    // let teacher_lims = &*teacher_limitation().read();
    // let mut lims = teachers_limitations().write();
    // let id = selected_teacher().read().unwrap();
    // lims.insert(id, teacher_lims.clone());
}

pub fn limitations_ui(ui: &mut egui::Ui) {
    let page = &*get_page().read();
    let acts = if let SubPage::Teachers = page {
        let id = selected_teacher().read().unwrap_or(1);
        let activities = teachers_acts().read().clone();
        let act = activities.get(&id).unwrap();
        act.clone()
    } else {
        let id = selected_class().read().unwrap_or(1);
        let activities = classes_acts().read().clone();
        let act = activities.get(&id).unwrap();
        act.clone()
    };
    match page {
        super::SubPage::Teachers => {
            if let Some(teacher_id) = *selected_teacher().read() {
                ui.set_width(1024.);
                Flex::vertical()
                    // .grow_items(0.5)
                    .gap(Vec2::new(0., 0.))
                    .show(ui, |flex| {
                        flex.add(
                            item(),
                            Label::new(
                                RichText::new(format!(
                                    "{}: {} saat",
                                    get_teachers_name(&[teacher_id]),
                                    teachers_acts_hours()
                                        .read()
                                        .clone()
                                        .get(&teacher_id)
                                        .unwrap()
                                ))
                                .size(24.),
                            ),
                        );
                        flex.add_ui(item(), |ui| ui.add_space(10.));
                        hours_frame(flex);
                        days_frame(
                            flex,
                            get_teacher_lims(teacher_id),
                            get_teacher_scheds(teacher_id),
                            teachers_volumes().read().get(&teacher_id).unwrap(),
                        );
                        flex.add_ui(item(), |ui| ui.add_space(10.));
                        flex.add_ui(item(), |ui| {
                            ui.horizontal(|ui| {
                                if ui
                                    .add_sized(Vec2::new(150., 50.), Button::new("Kaydet"))
                                    .clicked()
                                {
                                    save_teachers_limitations();
                                }
                                if ui
                                    .add_sized(Vec2::new(150., 50.), Button::new("Tümüne Uygula"))
                                    .clicked()
                                {
                                    change_all();
                                }
                            });
                        });
                    });
            } else {
                ui.label("Sol listeden seçim yapın");
            }
        }
        super::SubPage::Classes => {
            if let Some(class_id) = *selected_class().read() {
                ui.set_width(1024.);
                Flex::vertical()
                    // .grow_items(0.5)
                    .gap(Vec2::new(0., 0.))
                    .show(ui, |flex| {
                        flex.add(
                            item().grow(1.),
                            Label::new(RichText::new(get_classes_name(&[class_id])).size(24.)),
                        );
                        flex.add_ui(item(), |ui| ui.add_space(10.));
                        hours_frame(flex);
                        days_frame(
                            flex,
                            get_class_lims(class_id),
                            get_class_scheds(class_id),
                            classes_volumes().read().get(&class_id).unwrap(),
                        );
                        flex.add_ui(item(), |ui| ui.add_space(10.));
                        flex.add_ui(item(), |ui| {
                            ui.horizontal(|ui| {
                                if ui
                                    .add_sized(Vec2::new(150., 50.), Button::new("Kaydet"))
                                    .clicked()
                                {
                                    save_classes_limitations();
                                }
                                if ui
                                    .add_sized(Vec2::new(150., 50.), Button::new("Tümüne Uygula"))
                                    .clicked()
                                {
                                    change_all();
                                }
                            });
                        });
                    });
            } else {
                ui.label("Sol listeden seçim yapın");
            }
        }
    }
    acts_frames(ui, &acts);
}

fn hours_frame(flex: &mut FlexInstance) {
    let hour = school_hour().read().parse::<usize>().unwrap_or(8);
    let frame = Frame::none().stroke(Stroke::new(1., Color32::LIGHT_GRAY));
    flex.add_flex(
        item().grow(1.),
        Flex::horizontal().gap(vec2(0., 0.)),
        |flex| {
            flex.add_flex(item().frame(frame), Flex::new(), |flex| {
                flex.add_ui(item(), |ui| {
                    ui.add_sized(Vec2::new(100., 50.), Label::new("Günler ve Saatler"));
                });
            });
            for i in 0..hour {
                flex.add_flex(item().frame(frame), Flex::new(), |flex| {
                    flex.add_ui(item(), |ui| {
                        if ui
                            .add_sized(Vec2::new(100., 50.), Label::new((i + 1).to_string()))
                            .clicked()
                        {
                            change_all_hours(i);
                        };
                    })
                });
            }
        },
    );
}
// static LIMS: &[&[bool]] = &'static [&'static [true; 10]; 7];
fn days_frame(
    flex: &mut FlexInstance,
    _lims: Vec<Vec<bool>>,
    _scheds: Vec<Vec<Option<Activity>>>,
    vol: &Vec<Vec<i32>>,
) {
    let hour = school_hour().read().parse::<usize>().unwrap_or(8);
    let frame = Frame::none().stroke(Stroke::new(1., Color32::LIGHT_GRAY));
    for (index, day) in DAYS.iter().enumerate() {
        flex.add_flex(item(), Flex::horizontal().gap(Vec2::splat(0.)), |flex| {
            flex.add_flex(item().frame(frame), Flex::new(), |flex| {
                flex.add_ui(item(), |ui| {
                    if ui
                        .add_sized(Vec2::new(100., 50.), Label::new(*day))
                        .clicked()
                    {
                        change_all_day(index);
                    };
                });
            });
            for i in 0..hour {
                let v: u8 = if vol[index][i] > 100 {
                    100
                } else {
                    vol[index][i] as u8
                };
                let f_color = if _lims[index][i] {
                    Color32::from_rgb(50 + v * 2, 0, 0)
                } else {
                    Color32::default()
                };
                let frame = Frame::none()
                    .stroke(Stroke::new(1., Color32::LIGHT_GRAY))
                    .fill(f_color);
                flex.add_flex(item().grow(1.).frame(frame), Flex::vertical(), |ui| {
                    ui.add_ui(item(), |ui| {
                        ui.visuals_mut().widgets.inactive.bg_fill = egui::Color32::TRANSPARENT;
                        let (_, payl) = ui.dnd_drop_zone::<Activity, ()>(Frame::none(), |ui| {
                            sched_act(ui, &_scheds[index][i], index, i)
                        });
                        if let Some(p) = payl {
                            if p.teachers_available(i, index) && p.classes_available(i, index) {
                                std::thread::spawn(move || {
                                    if let Some(p_id) = partnered_act().read().get(&p.id) {
                                        let a = activities().read();
                                        let a = a.get(p_id).unwrap();
                                        data().write().put_act(index, i, &a.clone(), false);
                                    } else {
                                        data().write().put_act(index, i, &p.clone(), false);
                                    }
                                    data().write().replace_act(index, i, p.id, p.hour);
                                    // update_tt();
                                });
                            }
                            // println!("{p:?}");
                        }
                    });
                });
            }
        });
    }
}

pub fn create_teachers_sched() -> HashMap<i32, Vec<Vec<Option<Activity>>>> {
    let mut t_scheds = HashMap::new();
    let acts = activities().read().clone();
    let p_acts = partnered_act().read().clone();
    for teacher in &*get_teachers().read() {
        let mut teacher_acts = activities()
            .read()
            .iter()
            .filter(|a| a.1.teachers.iter().any(|c| c == &teacher.1.id))
            .map(|a| a.1.clone())
            .collect::<Vec<Activity>>();
        let p_ids = p_acts
            .iter()
            .filter(|pa| teacher_acts.iter().any(|ta| pa.0 == &ta.id))
            .map(|pa| pa.1.clone())
            .collect::<Vec<i32>>();
        for p_id in p_ids {
            if let Some(act) = acts.get(&p_id) {
                teacher_acts.push(act.clone());
            }
        }
        // let mut scheds = vec![];
        let scs = (*schedules().read()).clone();
        let sched = scs
            .iter()
            .filter(|s| teacher_acts.iter().any(|a| a.id == s.activity))
            .map(|s| s.clone())
            .collect::<Vec<Schedule>>();
        let mut scheduls: Vec<Vec<Option<Activity>>> =
            vec![vec![None; get_school().read().hour as usize]; 7];
        sched.iter().for_each(|s| {
            scheduls[s.day_id][s.hour as usize] = teacher_acts
                .clone()
                .into_iter()
                .find(|ca| ca.id == s.activity);
        });
        let t = teacher.1.clone();
        // let t_sched = Arc::clone(teacher_scheds());
        // std::thread::spawn(move || {
        t_scheds.insert(t.id, scheduls);
        // });
    }
    t_scheds
}
pub fn create_classes_sched() -> HashMap<i32, Vec<Vec<Option<Activity>>>> {
    let mut t_scheds = HashMap::new();
    for class in &*get_classes().read() {
        let class_acts = activities()
            .read()
            .iter()
            .filter(|a| a.1.classes.iter().any(|c| c == &class.1.id))
            .map(|a| a.1.clone())
            .collect::<Vec<Activity>>();
        // let mut scheds = vec![];
        let scs = (*schedules().read()).clone();
        let sched = scs
            .iter()
            .filter(|s| class_acts.iter().any(|a| a.id == s.activity))
            .map(|s| s.clone())
            .collect::<Vec<Schedule>>();
        let mut scheduls: Vec<Vec<Option<Activity>>> =
            vec![vec![None; get_school().read().hour as usize]; 7];
        sched.iter().for_each(|s| {
            scheduls[s.day_id][s.hour as usize] = class_acts
                .clone()
                .into_iter()
                .find(|ca| ca.id == s.activity);
        });
        let t = class.1.clone();
        // let t_sched = Arc::clone(class_scheds());
        // std::thread::spawn(move || {
        t_scheds.insert(t.id, scheduls);
        // });
    }
    t_scheds
}
fn sched_act(ui: &mut egui::Ui, a: &Option<Activity>, index: usize, i: usize) {
    let Some(a) = a else {
        if ui
            .add_sized(Vec2::new(100., 50.), Label::new(""))
            .on_hover_cursor(egui::CursorIcon::PointingHand)
            .clicked()
        {
            change_row(index, i);
        };
        return ();
    };
    let rtext = RichText::new(&a.lectures_name()).size(12.).strong();
    if ui
        .add_sized(Vec2::new(100., 15.), Label::new(rtext))
        .on_hover_cursor(egui::CursorIcon::PointingHand)
        .clicked()
    {
        change_row(index, i);
    };
    match *get_page().read() {
        SubPage::Teachers => {
            let rtext = RichText::new(&a.classes_name()).size(16.).strong();
            if ui
                .add_sized(vec2(100., 20.), Label::new(rtext))
                .on_hover_cursor(egui::CursorIcon::PointingHand)
                .clicked()
            {
                change_row(index, i);
            };
        }
        SubPage::Classes => {
            let rtext = RichText::new(&a.teachers_short_name()).size(10.).strong();
            if ui
                .add_sized(vec2(100., 15.), Label::new(rtext))
                .on_hover_cursor(egui::CursorIcon::PointingHand)
                .clicked()
            {
                change_row(index, i);
            };
        }
    }
    ui.horizontal(|ui| {
        let rtext = RichText::new("🗑").size(16.).strong();
        if ui
            .add_sized(Vec2::new(45., 15.), Label::new(rtext))
            .on_hover_cursor(egui::CursorIcon::PointingHand)
            .clicked()
        {
            del_tt(a.id);
        };
        let color = if is_lock_tt(a.id) {
            Color32::BLUE
        } else {
            Color32::GRAY
        };
        let ltext = RichText::new("🔒").size(16.).color(color).strong();
        if ui
            .add_sized(Vec2::new(45., 15.), Label::new(ltext))
            .on_hover_cursor(egui::CursorIcon::PointingHand)
            .clicked()
        {
            lock_tt(a.id);
        };
    });
    // ui.add(Label::new());
    // format!("{}\n{}", a.lectures_name(), a.teachers_short_name())
}

fn lock_tt(act_id: i32) {
    std::thread::spawn(move || {
        let dt: &mut TimetableData = &mut *data().write();
        let scheds = &mut dt.timetables;
        let sched = scheds.get_mut(&act_id);
        if let Some(tt) = sched {
            tt.iter_mut().for_each(|t| t.locked = !t.locked);
        }
        update_tt();
    });
}
fn del_tt(act_id: i32) {
    std::thread::spawn(move || {
        let dt: &mut TimetableData = &mut *data().write();
        let scheds = &mut dt.timetables;
        let sched = scheds.remove(&act_id);
        update_tt();
    });
}

pub fn update_tt() {
    std::thread::spawn(move || {
        let dt: &mut TimetableData = &mut *data().write();
        let scheds = &mut dt.timetables;
        let mut sch = vec![];
        scheds.values().for_each(|tt| sch.append(&mut tt.clone()));
        *schedules().write() = sch.clone();
        *classes_sched().write() = create_classes_sched();
        *teachers_scheds().write() = create_teachers_sched();
        *classes_volumes().write() = create_classes_volumes();
        *teachers_volumes().write() = create_teachers_volumes();
    });
}
fn is_lock_tt(act_id: i32) -> bool {
    let scheds: &Vec<Schedule> = &*schedules().write();
    let sched = scheds.iter().find(|a| a.activity == act_id);
    if let Some(tt) = sched {
        return tt.locked;
    }
    return false;
}
fn change_all_day(day: usize) {
    std::thread::spawn(move || {
        let page = &*get_page().read();
        match page {
            super::SubPage::Teachers => {
                let lims = &*teachers_limitations();
                let lim = Arc::clone(lims);
                std::thread::spawn(move || {
                    let lims = &mut lim.write();
                    let day = &mut lims
                        .get_mut(&selected_teacher().read().unwrap())
                        .unwrap()
                        .limitations[day];
                    if day.iter().any(|h| !*h) {
                        *day = vec![true; 10];
                    } else {
                        *day = vec![false; 10];
                    }
                });
            }
            super::SubPage::Classes => {
                let lims = &*classes_limitations();
                let lim = Arc::clone(lims);
                std::thread::spawn(move || {
                    let lims = &mut lim.write();
                    let day = &mut lims
                        .get_mut(&selected_class().read().unwrap())
                        .unwrap()
                        .limitations[day];
                    if day.iter().any(|h| !*h) {
                        *day = vec![true; 10];
                    } else {
                        *day = vec![false; 10];
                    }
                });
            }
        }
    });
}

fn change_all_hours(hour: usize) {
    std::thread::spawn(move || {
        let page = &*get_page().read();
        match page {
            super::SubPage::Teachers => {
                let lims = &*teachers_limitations();
                let lim = Arc::clone(lims);
                std::thread::spawn(move || {
                    let lims = &mut lim.write();
                    let lims = &mut lims
                        .get_mut(&selected_teacher().read().unwrap())
                        .unwrap()
                        .limitations;
                    if lims.iter().any(|h| !h[hour]) {
                        lims.iter_mut().for_each(|d| d[hour] = true);
                    } else {
                        lims.iter_mut().for_each(|d| d[hour] = false);
                        // *day = vec![false; 10];
                    }
                    // lim.write().limitations[day][hour] = !row;
                });
            }
            super::SubPage::Classes => {
                let lims = &*classes_limitations();
                let lim = Arc::clone(lims);
                std::thread::spawn(move || {
                    let lims = &mut lim.write();
                    let lims = &mut lims
                        .get_mut(&selected_class().read().unwrap())
                        .unwrap()
                        .limitations;
                    if lims.iter().any(|h| !h[hour]) {
                        lims.iter_mut().for_each(|d| d[hour] = true);
                    } else {
                        lims.iter_mut().for_each(|d| d[hour] = false);
                    }
                });
            }
        }
    });
}
pub fn save_teachers_limitations() {
    spawn(move || {
        let lims = &*teachers_limitations().read();
        let lims = lims.values().collect::<Vec<&TeacherLimitation>>();
        let mut f = File::create("./db/teachers_limitations.json").unwrap();
        f.write_all(serde_json::to_string(&lims).unwrap().as_bytes())
            .unwrap();
        *available_days().write() = create_available_days();
    });
}

pub fn save_classes_limitations() {
    let lims = &*classes_limitations().read();
    let lims = lims.values().collect::<Vec<&ClassLimitation>>();
    let mut f = File::create("./db/classes_limitations.json").unwrap();
    f.write_all(serde_json::to_string(&lims).unwrap().as_bytes())
        .expect("Sınıf Kısıtları Yazılamadı");
}
fn change_row(day: usize, hour: usize) {
    std::thread::spawn(move || {
        let page = &*get_page().read();
        match page {
            SubPage::Teachers => {
                let c_id = selected_teacher().read().unwrap();
                let mut lims = teachers_limitations().write();
                let row = lims.get_mut(&c_id);
                if let Some(r) = row {
                    r.limitations[day][hour] = !r.limitations[day][hour];
                }
            }
            SubPage::Classes => {
                let c_id = selected_class().read().unwrap();
                let mut lims = classes_limitations().write();
                let row = lims.get_mut(&c_id);
                if let Some(r) = row {
                    r.limitations[day][hour] = !r.limitations[day][hour];
                }
            }
        }
    });
}

fn change_all() {
    let page = get_page();
    match &*page.read() {
        SubPage::Teachers => {
            change_all_teachers();
        }
        SubPage::Classes => {
            change_all_classes();
        }
    }
}

fn change_all_teachers() {
    let t_id = selected_teacher().read().unwrap();
    let teachers_lims = teachers_limitations().read().clone();
    let t_lims = teachers_lims.get(&t_id).unwrap().clone();
    std::thread::spawn(move || {
        let t_lims = t_lims.clone();
        let teachers = &*get_teachers().read();
        for t in teachers {
            let lims = &mut *teachers_limitations().write();
            if let Some(lims) = lims.get_mut(&t.1.id) {
                lims.limitations = t_lims.limitations.clone();
            }
        }
    });
}
fn change_all_classes() {
    let c_id = selected_class().read().unwrap();
    let classes_lims = classes_limitations().read().clone();
    let c_lims = classes_lims.get(&c_id).unwrap().clone();
    std::thread::spawn(move || {
        let c_lims = c_lims.clone();
        let classes = &*get_classes().read();
        for c in classes {
            let lims = &mut *classes_limitations().write();
            if let Some(lims) = lims.get_mut(&c.1.id) {
                lims.limitations = c_lims.limitations.clone();
            }
        }
    });
}