use std::{
collections::HashMap,
fs::File,
io::{Read, Write},
path::{Path, PathBuf},
sync::{Arc, OnceLock},
time::Instant,
};
use chrono::Local;
use eframe::egui::{mutex::RwLock, vec2, Button, ProgressBar, TextEdit};
use egui::Context;
use egui_flex::{item, Flex};
use rfd::FileDialog;
use super::{
activities::{activities, partnered_act, selected_act},
generating::{data, generate, Schedule},
limitations::limitations_ui::{
classes_sched, create_classes_sched, create_teachers_sched, schedules, teachers_scheds,
},
print_pdf::{classes::classes_prints, teachers::teachers_prints},
};
pub fn params_hour() -> &'static RwLock<String> {
static PARAM: OnceLock<RwLock<String>> = OnceLock::new();
PARAM.get_or_init(|| RwLock::new("".to_string()))
}
pub fn total_hours() -> &'static RwLock<f32> {
static PARAM: OnceLock<RwLock<f32>> = OnceLock::new();
PARAM.get_or_init(|| RwLock::new(create_total_hours()))
}
pub fn create_total_hours() -> f32 {
activities()
.read()
.clone()
.values()
.filter(|a| partnered_act().read().get(&a.id).is_none())
.fold(0., |acc, x| acc + x.hour as f32)
}
pub fn continued() -> &'static RwLock<bool> {
static PARAM: OnceLock<RwLock<bool>> = OnceLock::new();
PARAM.get_or_init(|| RwLock::new(false))
}
pub fn generating() -> &'static Arc<RwLock<bool>> {
static GENERATING: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();
GENERATING.get_or_init(|| Arc::new(RwLock::new(false)))
}
pub fn multi_thread() -> &'static Arc<RwLock<bool>> {
static GENERATING: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();
GENERATING.get_or_init(|| Arc::new(RwLock::new(false)))
}
pub fn recalc_sched() -> HashMap<i32, Vec<Schedule>> {
let schdls = &*schedules().read();
let mut map: HashMap<i32, Vec<Schedule>> = HashMap::new();
for s in schdls {
let acts = activities().read();
if let Some(a) = acts.get(&s.activity) {
if let Some(tt) = map.get_mut(&a.id) {
tt.push(s.clone());
} else {
map.insert(a.id, vec![s.clone()]);
};
};
}
map
}
pub fn generate_ui(ui: &mut eframe::egui::Ui) {
ui.vertical_centered(|ui| {
ui.add_sized(
vec2(400., 30.),
TextEdit::singleline(&mut *params_hour().write())
.hint_text("Bir öğretmenin aynı sınıfa verebileceği ders saati sayısı"),
);
ui.add_space(10.);
ui.add(
ProgressBar::new(schedules().read().len() as f32 / *total_hours().read())
.desired_width(400.)
.desired_height(50.)
.text(format!(
" {}/{}",
schedules().read().len(),
total_hours().read()
))
.animate(*continued().read())
.corner_radius(5),
);
ui.add_space(10.);
if *generating().read() {
if ui
.add_sized(vec2(400., 30.), Button::new("Durdur"))
.clicked()
{
*generating().write() = false;
}
} else {
if *continued().read() {
if ui
.add_sized(vec2(400., 30.), Button::new("Devam Et"))
.clicked()
{
*generating().write() = true;
generate();
}
} else {
if ui
.add_sized(vec2(400., 30.), Button::new("Çalıştır"))
.clicked()
{
*generating().write() = true;
*continued().write() = true;
generate();
};
}
}
if ui
.add_sized(vec2(400., 30.), Button::new("Sıfırla"))
.clicked()
{
let mut sch = vec![];
data()
.write()
.timetables
.retain(|_id, tt| tt.iter().any(|t| t.locked));
data()
.read()
.timetables
.values()
.for_each(|tt| sch.append(&mut tt.clone()));
*schedules().write() = sch.clone();
*teachers_scheds().write() = create_teachers_sched();
*classes_sched().write() = create_classes_sched();
*total_hours().write() = create_total_hours();
}
ui.layout().horizontal_justify();
Flex::horizontal()
.wrap(true)
.width_percent(1.)
.grow_items(1.)
.show(ui, |flex| {
flex.add_ui(item(), |ui| {
if ui
.add_sized(vec2(197., 30.), Button::new("Sınıf Programını Yazdır"))
.clicked()
{
classes_prints();
}
if ui
.add_sized(vec2(197., 30.), Button::new("Öğretmen Programını Yazdır"))
.clicked()
{
teachers_prints();
}
});
});
ui.label(format!("{:?}", *selected_act().read()));
if ui
.add_sized(vec2(197., 30.), Button::new("Programı Kaydet"))
.clicked()
{
save_scheds();
}
if ui
.add_sized(vec2(197., 30.), Button::new("Programı Aç"))
.clicked()
{
open_scheds();
}
});
}
pub fn save_scheds() {
std::thread::spawn(move || {
let scheds = &*schedules().read();
let js = serde_json::to_string(&*scheds.clone());
match js {
Ok(j) => {
let date = Local::now();
let file_name = format!("./db/scheds/{}.json", date.format("%Y-%m-%d %H:%M"));
let mut f = File::create(file_name).unwrap();
f.write_all(j.as_bytes()).unwrap();
}
Err(_) => {}
}
});
}
pub fn read_scheds(path: PathBuf) {
std::thread::spawn(move || {
let f = File::open(path);
if let Ok(mut f) = f {
let mut content: String = String::new();
f.read_to_string(&mut content).unwrap();
let cls: Vec<Schedule> = serde_json::from_str(content.as_str()).unwrap();
let data = &mut *data().write();
let tt = &mut data.timetables;
for sch in &cls {
tt.entry(sch.activity)
.and_modify(|a| a.push(sch.clone()))
.or_insert(vec![sch.clone()]);
}
*schedules().write() = cls;
}
});
}
pub fn open_scheds() {
let file = FileDialog::new()
.set_title("Dosya Seç")
.set_directory("./db/scheds")
.pick_file();
read_scheds(file.unwrap());
}