use config::Config;
use std::io::prelude::*;
use std::io::BufReader;
use std::process::{ChildStdin, ChildStdout, Command, Stdio};
use std::thread;

pub struct Bar {
    stdin: ChildStdin
}

impl Bar {
    pub fn new(top: bool, cfg: &Config) -> Bar {
        let val = cfg.lookup("bar.fonts").unwrap();
        let fonts = val.as_slice().unwrap();
        let fonts = fonts.iter().flat_map(|elem| elem.as_str());

        let mut bar = Command::new("lemonbar");
        bar.stdin(Stdio::piped());
        bar.stdout(Stdio::piped());

        if !top {
            bar.arg("-b");
        }

        for font in fonts {
            bar.arg("-f");
            bar.arg(font);
        }

        let child = bar.spawn()
            .ok()
            .expect("Failed to start lemonbar");

        let stdout = child.stdout.unwrap();
        Bar::read_loop(stdout);

        Bar { stdin: child.stdin.unwrap() }
    }

    fn read_loop(stdout: ChildStdout) {
        thread::spawn(move || {
            let mut s = String::new();
            let mut reader = BufReader::new(stdout);
            loop {
                s.clear();
                reader.read_line(&mut s).ok().expect("Failed to read from lemonbar");

                let mut chars = s.trim().chars();
                let kind = chars.next().unwrap();
                let name = chars.collect::<String>();

                match kind {
                    'w' => Command::new("bspc")
                        .arg("desktop")
                        .arg("-f")
                        .arg(&name)
                        .output()
                        .ok(),

                    'c' => Command::new("cmus-remote")
                        .arg("--pause")
                        .output()
                        .ok(),

                    'm' => Command::new("mpc")
                        .arg("toggle")
                        .output()
                        .ok(),

                    _ => None
                };
            }
        });
    }

    pub fn send(&mut self, text: &str) {
        writeln!(&mut self.stdin, "{}", text).ok();
    }
}