use eframe::egui;
use eframe::egui::mutex::RwLock;
use eframe::egui::vec2;
use eframe::egui::Align2;
use eframe::egui::Button;
use eframe::egui::Color32;
use eframe::egui::Label;
use eframe::egui::Link;
use eframe::egui::RichText;
use eframe::egui::Stroke;
use eframe::egui::TextEdit;
use egui::TextBuffer;
// use eframe::Frame;
use egui_flex::item;
use egui_flex::Flex;
use serde::Deserialize;
use serde::Serialize;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::iter::zip;
use std::sync::Arc;
use std::sync::OnceLock;

use super::activities::activities;
use super::activities::activity_form::filtered_lectures;
use super::activities::activity_form::filtering_lectures;
use super::activities::activity_form::lectures_ui::set_lecture_filter;
use super::activities::save_activities;
use super::activities::Activity;
use super::classes::get_classes;

#[derive(Clone, Serialize, Deserialize, Debug, Default)]
pub struct Lecture {
    pub id: i32,
    pub name: String,
    pub short_name: String,
}

impl Display for Lecture {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.name)
    }
}

pub fn lec_del_states() -> &'static Arc<RwLock<Vec<bool>>> {
    static LECTURES: OnceLock<Arc<RwLock<Vec<bool>>>> = OnceLock::new();
    LECTURES.get_or_init(|| Arc::new(RwLock::new(vec![false; filtered_lectures().read().len()])))
}
pub fn create_states() -> Vec<bool> {
    vec![false; filtered_lectures().read().len()]
}

pub fn class_lectures() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>> {
    static LECTURES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>>> = OnceLock::new();
    LECTURES.get_or_init(|| Arc::new(RwLock::new(create_class_lectures())))
}
pub fn not_class_lectures() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>> {
    static LECTURES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>>> = OnceLock::new();
    LECTURES.get_or_init(|| Arc::new(RwLock::new(not_create_class_lectures())))
}
pub fn get_lectures() -> &'static Arc<RwLock<BTreeMap<i32, Lecture>>> {
    static LECTURES: OnceLock<Arc<RwLock<BTreeMap<i32, Lecture>>>> = OnceLock::new();
    LECTURES.get_or_init(|| Arc::new(RwLock::new(read_lectures())))
}
pub fn lec_name() -> &'static Arc<RwLock<String>> {
    static NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();
    NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))
}
pub fn selected_lec() -> &'static Arc<RwLock<i32>> {
    static NAME: OnceLock<Arc<RwLock<i32>>> = OnceLock::new();
    NAME.get_or_init(|| Arc::new(RwLock::new(-1)))
}
pub fn lec_short_name() -> &'static Arc<RwLock<String>> {
    static SHORT_NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();
    SHORT_NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))
}
fn update_lec_form() -> &'static Arc<RwLock<bool>> {
    static SHORT_NAME: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();
    SHORT_NAME.get_or_init(|| Arc::new(RwLock::new(false)))
}
fn update_lec(ui: &mut eframe::egui::Ui) {
    egui::Window::new("Update Lecture")
        .open(&mut *update_lec_form().write())
        .resizable([true, true])
        .show(ui.ctx(), |ui| {
            ui.add(TextEdit::singleline(&mut *lec_name().write()));
            ui.add(TextEdit::singleline(&mut *lec_short_name().write()));
            if ui.add(Button::new("Güncelle")).clicked() {
                if let Some(t) = get_lectures().write().get_mut(&selected_lec().read()) {
                    t.name = lec_name().read().clone();
                    t.short_name = lec_short_name().read().clone();
                    save_lectures();
                    lec_name().write().clear();
                    lec_short_name().write().clear();
                    set_lecture_filter();
                    *update_lec_form().write() = false;
                }
            }
        });
}
pub fn lectures_page(ui: &mut eframe::egui::Ui) {
    // let mut name = get_name().lock().unwrap();
    ui.vertical_centered(|ui| {
        if ui
            .add_sized(
                vec2(250., 30.),
                TextEdit::singleline(&mut *lec_name().write()).hint_text("Ders Adını Gir"),
            )
            .changed()
        {
            set_lecture_filter();
        };
        ui.add_sized(
            vec2(250., 30.),
            TextEdit::singleline(&mut *lec_short_name().write()).hint_text("Kısa Adı"),
        );
        if ui.add_sized(vec2(250., 30.), Button::new("Ekle")).clicked() {
            add_lec();
        }
    });
    ui.separator();
    lectures_ui(ui);
}
fn add_lec() {
    let new_id = find_new_id();
    let new_lec = Lecture {
        id: new_id,
        name: lec_name().write().clone(),
        short_name: lec_short_name().write().clone(),
    };
    std::thread::spawn(move || {
        let lecs = get_lectures();
        lecs.write().insert(new_id, new_lec);
        *lec_name().write() = "".to_string();
        *lec_short_name().write() = "".to_string();
        set_lecture_filter();
        *filtered_lectures().write() = filtering_lectures();
        save_lectures();
        lec_del_states().write().push(false);
    });
}
fn lectures_ui(ui: &mut eframe::egui::Ui) {
    update_lec(ui);
    Flex::horizontal()
        // .grow_items(1.)
        .wrap(true)
        .gap(vec2(20., 20.))
        .show(ui, |flex| {
            let del_states = lec_del_states().read().clone();
            let del_states = del_states.iter().enumerate();
            for (del_state, lecture) in zip(del_states, filtered_lectures().read().iter()) {
                let frame = egui::Frame::default()
                    .stroke(Stroke::new(0.3, Color32::GRAY))
                    .rounding(5.)
                    .inner_margin(10.);
                flex.add_flex(
                    item().grow(1.).frame(frame),
                    Flex::vertical().align_items_content(Align2::CENTER_TOP),
                    |flex| {
                        flex.add(item(), Label::new(&lecture.name));
                        if *del_state.1 {
                            flex.add_flex(
                                item().grow(1.),
                                Flex::horizontal().align_items(egui_flex::FlexAlign::Center),
                                |flex| {
                                    if flex
                                        .add(
                                            item().grow(1.),
                                            Link::new(
                                                RichText::new("Sil").color(Color32::LIGHT_RED),
                                            ),
                                        )
                                        // .inner
                                        .clicked()
                                    {
                                        del_lecture(lecture.id);
                                    };
                                    if flex
                                        .add(item().grow(1.), Link::new("Vazgeç"))
                                        // .inner
                                        .clicked()
                                    {
                                        change_state(del_state.0);
                                    };
                                },
                            );
                        } else {
                            if flex
                                .add(
                                    item(),
                                    Link::new(RichText::new("Sil").color(Color32::DARK_RED)),
                                )
                                // .inner
                                .clicked()
                            {
                                change_state(del_state.0);
                            }
                            if flex.add(item(), Link::new("Düzenle")).clicked() {
                                let c = lecture.clone();
                                *selected_lec().write() = c.id;
                                std::thread::spawn(move || {
                                    *lec_name().write() = c.name.clone();
                                    *lec_short_name().write() = c.short_name.clone();
                                    *update_lec_form().write() = true;
                                });
                            }
                        }
                    },
                );
            }
        });
}

fn change_state(state: usize) {
    std::thread::spawn(move || {
        if let Some(st) = lec_del_states().write().get_mut(state) {
            *st = !*st;
        }
    });
}

fn save_lectures() {
    std::thread::spawn(move || {
        let lectures = get_lectures().read();
        let js = serde_json::to_string(&*lectures);
        match js {
            Ok(j) => {
                let mut f = File::create("./db/lectures.json").unwrap();
                f.write_all(j.as_bytes()).unwrap();
            }
            Err(_) => {}
        }
    });
}
fn read_lectures() -> BTreeMap<i32, Lecture> {
    let f = File::open("./db/lectures.json");
    if let Ok(mut f) = f {
        let mut content: String = String::new();
        f.read_to_string(&mut content).unwrap();
        let cls: BTreeMap<i32, Lecture> = serde_json::from_str(content.as_str()).unwrap();
        return cls;
    }
    BTreeMap::new()
}

fn create_class_lectures() -> BTreeMap<i32, Vec<Lecture>> {
    let mut map = BTreeMap::new();
    let cls = get_classes().read();
    let acts = &*activities().read();
    let lecs = get_lectures()
        .read()
        .values()
        .map(|l| l.clone())
        .collect::<Vec<Lecture>>();
    for c in &*cls {
        let c_acts = acts
            .values()
            .filter(|a| a.classes.iter().any(|ac| ac == &c.1.id))
            .map(|a| a.clone())
            .collect::<Vec<Activity>>();
        let lec = &lecs
            .iter()
            .filter(|l| c_acts.iter().any(|a| a.lecture == l.id))
            .map(|l| l.clone())
            .collect::<Vec<Lecture>>();
        map.insert(c.1.id, lec.clone());
    }
    map
}
fn not_create_class_lectures() -> BTreeMap<i32, Vec<Lecture>> {
    let mut map = BTreeMap::new();
    let cls = get_classes().read();
    // let acts = &*activities().read();
    let lecs = get_lectures()
        .read()
        .values()
        .map(|l| l.clone())
        .collect::<Vec<Lecture>>();
    let c_lecs = class_lectures().read().clone();
    for c in &*cls {
        let c_lecs = c_lecs.get(&c.1.id);
        if let Some(cl) = c_lecs {
            let mut l = lecs.clone();
            l.retain(|l| !cl.iter().any(|cl| cl.id == l.id));
            map.insert(c.1.id, l.clone());
        } else {
            map.insert(c.1.id, lecs.clone());
        }
        // let lec = &lecs.retain(|l| class_lectures().read().values().any(|cl| cl. =))
        // map.insert(c.1.id, lec.clone());
    }
    map
}
fn del_lecture(id: i32) {
    let lectures = get_lectures().clone();
    let cls = Arc::clone(&lectures);
    std::thread::spawn(move || {
        cls.write().remove(&id);
        save_lectures();
        *filtered_lectures().write() = filtering_lectures();
        *lec_del_states().write() = create_states();
        let acts = &mut *activities().write();
        acts.retain(|_a, b| b.lecture != id);
        save_activities();
    });
}
fn find_new_id() -> i32 {
    let len = get_lectures().read().len() as i32;
    for i in 1..len + 1 {
        if !get_lectures().read().contains_key(&i) {
            return i;
        }
    }
    len + 1
}