mod font;
mod panel;
mod ext;
mod title;
mod tray;
mod sensors;
mod bspwm;
mod spacer;
mod util;
mod widget;
mod x11;

use simple_signal;
use simple_signal::Signal;
use config::Config;

use std::sync::mpsc;
use std::thread;
use std::time;

pub const SIZE: u16 = 20;

pub fn ui_main(cfg: &Config) -> i32 {
    if let Some(conn) = x11::Connection::new() {
        let (tx, rx) = mpsc::channel();
        {
            let tx = tx.clone();
            simple_signal::set_handler(&[Signal::Int, Signal::Term], move |_signals| {
                tx.send(widget::Message::Quit).expect("Failed to send quit");
            });
        }
        {
            let tx = tx.clone();
            let conn = conn.clone_connection();
            thread::spawn(move || {
                loop {
                    match conn.wait_for_event() {
                        Some(event) => {
                            let message = widget::Message::XcbEvent(event);
                            tx.send(message).expect("Failed to send xcb event");
                        },
                        None => { break; }
                    }
                }
            });
        }

        let mut panel = panel::Panel::new(conn, cfg);

        let bspwm = bspwm::Bspwm::new(tx.clone(), panel.make_draw_context());
        panel.add_left_widget(Box::new(bspwm));

        let spacer = spacer::create(panel.make_draw_context(), 4, 0x6666, 0x6666, 0x6666, 0xFFFF);
        panel.add_left_widget(Box::new(spacer));

        let title = title::Title::new(panel.conn.clone(), panel.make_draw_context());
        panel.add_left_widget(Box::new(title));

        let tray = tray::Tray::new(tx.clone(), panel.conn.clone(), panel.window);
        panel.add_right_widget(Box::new(tray));

        let sensors = sensors::Sensors::new(panel.make_draw_context(), cfg);
        panel.add_right_widget(Box::new(sensors));

        panel.create();

        {
            let tx = tx.clone();
            thread::spawn(move || {
                loop {
                    tx.send(widget::Message::Update).expect("Failed to send update");
                    thread::sleep(time::Duration::from_secs(1));
                }
            });
        }

        loop {
            let event = rx.recv();
            if panel.handle_event(event.unwrap()) {
                println!("Exiting");
                break;
            }
        }
    }
    0
}