// Build a tree of folders (not files)
// Folders can be expanded and collapsed
// Folders can by selected
// Folders will fetch their children when expanded

use std::path::PathBuf;

use eframe::egui;

pub struct Tree {
    root: Folder,
    pub selected: PathBuf,
}

impl Tree {
    pub fn new() -> Self {
        Self {
            root: Folder::new("./tmp", "./tmp"),
            selected: PathBuf::new(),
        }
    }

    pub fn set_root_path(&mut self, path: impl Into<PathBuf>) {
        let path: PathBuf = path.into();

        let name = path.to_string_lossy().to_string();

        self.root = Folder::new(name, path);
    }

    pub fn show(&mut self, ui: &mut egui::Ui) {
        ui.vertical(|ui| {
            self.root.show(ui, &mut self.selected);
        });
    }
}

pub struct Folder {
    name: String,
    path: PathBuf,
    expanded: bool,
    children: Option<Vec<Folder>>,
    // selected: Arc<RwLock<PathBuf>>,
}

impl Folder {
    pub fn new(name: impl Into<String>, path: impl Into<PathBuf>) -> Self {
        Self {
            name: name.into(),
            path: path.into(),
            expanded: false,
            children: Default::default(),
        }
    }

    pub fn show(&mut self, ui: &mut egui::Ui, selected: &mut PathBuf) {
        let Self {
            name,
            path,
            expanded,
            children,
        } = self;

        if children.is_none() {
            let mut children_data = vec![];
            println!("Reading dir: {:?}", path);
            std::fs::read_dir(&path)
                .map(|entries| {
                    for entry in entries.flatten() {
                        let path = entry.path();
                        if path.is_dir() {
                            println!(
                                "Found dir: {:?}, file {}, link {}",
                                path,
                                path.is_file(),
                                path.is_symlink()
                            );
                            let path2 = path.clone();
                            let name = path2.file_name().unwrap().to_string_lossy();
                            children_data.push(Folder::new(name, path));
                        }
                    }
                })
                .unwrap_or_else(|err| {
                    eprintln!("Failed to read dir: {}", err);
                });
            children.replace(children_data);
        }

        ui.horizontal(|ui| {
            if let Some(children) = children {
                if !children.is_empty() {
                    let label = if *expanded { "▼" } else { "▶" };
                    let response = ui.selectable_label(false, label);

                    if response.clicked() && !children.is_empty() {
                        *expanded = !*expanded;
                    }
                }
            } else {
                ui.label("⌛");
            }

            if ui
                .selectable_label(*selected == *path, name.to_owned())
                .clicked()
            {
                *selected = path.clone();
            }
        });

        if let Some(children) = children {
            if *expanded {
                ui.indent("", |ui| {
                    for child in children {
                        child.show(ui, selected);
                    }
                });
            }
        }
    }
}
