extern crate lazy_static;

extern crate eframe;
extern crate egui;
extern crate mango_egui;

mod presets;
mod util;

use std::{
    env::var,
    path::Path,
    sync::Arc,
    thread::spawn,
};

use duct::cmd;
use egui::{mutex::Mutex, Ui};
use lazy_static::lazy_static;
use mango_egui::{version, InfoBar, About, License, LoadFiles};

use util::init;

const UNI_R_ARROW: &'static str = "➡";

fn ffmpeg_path() -> String {
    var("CHIAKI_FFMPEG").unwrap_or("ffmpeg".into())
}

//const BANNER: &'static str = include_str!("BANNER.txt");

lazy_static! {
    static ref HOME: String = std::env::var("HOME").unwrap();
}

#[derive(Default, Clone)]
pub struct Job {
    ipath: String,
    opath: String,
    args: Vec<String>,
}
pub struct Chiaki {
    pr_index: Arc<Mutex<usize>>,
    info_bar: InfoBar,

    running: Arc<Mutex<bool>>,

    input: LoadFiles,
    project: Arc<Mutex<String>>,

    current: Arc<Mutex<Option<Job>>>,
    jobs: Arc<Mutex<Vec<Job>>>,
}

fn file_name(path: String) -> String {
    Path::new(&path).file_name().unwrap().to_str().unwrap().to_string()
}
fn job(ui: &mut Ui, j: Job) {
    ui.label(file_name(j.ipath.clone()));
    ui.label(UNI_R_ARROW);
    ui.label(file_name(j.opath.clone())); 
}

impl eframe::App for Chiaki {
    fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
        if !*self.running.lock() {
            ctx.set_pixels_per_point(1.5);
        }
        egui::gui_zoom::zoom_with_keyboard_shortcuts(ctx, frame.info().native_pixels_per_point); 
        egui::CentralPanel::default().show(ctx, |ui| {
            let prs = presets::from(init());
            let pr_index = *self.pr_index.lock();

            ui.add(self.input.clone());
            {
                ui.label("project name");
                ui.text_edit_singleline(&mut *self.project.lock());
            }
            {
                ui.label("preset");
                egui::ComboBox::from_id_source("preset_dropdown")
                    .selected_text(prs.get(pr_index).unwrap().name.clone())
                    .show_ui(ui, |ui| {
                        for (i, pr) in prs.iter().enumerate() {
                            if ui
                                .selectable_label(*self.pr_index.lock() == i, pr.name.clone())
                                .clicked()
                            {
                                (*self.pr_index.lock()) = i;
                            }
                        }
                    });
            }
            if ui.button("run").clicked() {
                for (i, ipath) in self.input.paths().iter().enumerate() {
                    (*self.jobs.lock()).push(Job {
                        ipath: ipath.clone(),
                        opath: format!("{}_{}.mkv", *self.project.lock(), i),
                        args: prs.get(pr_index.clone()).unwrap().clone().args.clone(),
                    });
                }
            }
            if let Some(j) = (*self.current.lock()).clone() {
                ui.group(|ui| ui.horizontal(|ui| {
                    ui.spinner();
                    job(ui, j);
                }));
            } else {
                ui.vertical_centered(|ui| ui.label("no jobs running or in queue"));
            }
            {
                let jobs = (*self.jobs.lock()).clone();
                for j in jobs {
                    ui.group(|ui| ui.horizontal(|ui| {
                        job(ui, j);
                    }));
                }
            }
            if !*self.running.lock() {
                *self.running.lock() = true;

                let current = Arc::clone(&self.current);
                let jobs = Arc::clone(&self.jobs);
                spawn(move || {
                    loop {
                        let j = (*jobs.lock()).pop();
                        if j.is_some() {
                            let j = j.unwrap();
                            *current.lock() = Some(j.clone());
                            let mut a: Vec<String> = Vec::new();

                            a.push("-i".to_string());
                            a.push(j.ipath.clone());
                            a.extend(j.args.clone());
                            a.push(j.opath.clone());
                            a.push("-y".to_string());

                            cmd(ffmpeg_path(), a.as_slice().clone()).run().unwrap();

                            *current.lock() = None;
                        }
                    }
                });
            }

            ui.add(self.info_bar.clone());
        });
    }
}

fn main() -> std::io::Result<()> {
    eframe::run_native(
        "chiaki",
        eframe::NativeOptions {
            drag_and_drop_support: true,
            ..Default::default()
        },
        Box::new(|_| {
            Box::new(Chiaki {
                pr_index: Arc::new(Mutex::new(0)),
                running: Arc::new(Mutex::new(false)),

                input: LoadFiles::new("input"),
                project: Arc::new(Mutex::new(String::new())),
                
                current: Arc::new(Mutex::new(None)),
                jobs: Arc::new(Mutex::new(Vec::new())),

                info_bar: InfoBar {
                    source_url: Some("https://github.com/ripe-mangos/chiaki"),
                    bug_tracker_url: Some("https://github.com/ripe-mangos/chiaki/issues"),
                    version: version!(),

                    about: About {
                        name: "chiaki",
                        description: "simple ffmpeg helper",
                    },
                    licenses: &[
                        License {
                            name: "egui",
                            license: "MIT / Apache-2.0",
                            copyright: "(c) Emil Ernerfeldt",
                            source_url: Some("https://github.com/emilk/egui"),
                        },
                        License {
                            name: "eframe",
                            license: "MIT / Apache-2.0",
                            copyright: "(c) Emil Ernerfeldt",
                            source_url: Some("https://github.com/emilk/egui"),
                        },
                        License {
                            name: "duct",
                            license: "MIT",
                            copyright: "(c) oconnor663",
                            source_url: Some("https://github.com/oconnor663/duct.rs"),
                        },
                        License {
                            name: "rfd",
                            license: "MIT",
                            copyright: "(c) 2022 Bartłomiej Maryńczak",
                            source_url: Some("https://github.com/PolyMeilex/rfd"),
                        },
                        License {
                            name: "owo-colors",
                            license: "MIT",
                            copyright: "(c) 2020 - present The owo-colors Developers",
                            source_url: Some("https://github.com/jam1garner/owo-colors"),
                        },
                        License {
                            name: "mango-egui",
                            license: "MIT",
                            copyright: "(c) 2022 Lincoln Williams",
                            source_url: None,
                        },
                    ],

                    ..InfoBar::default()
                },
            })
        }),
    );

    Ok(())
}
