use dbus::{channel::MatchingReceiver, message::MatchRule};
use dbus_crossroads::Crossroads;
use dbus_tokio::connection;
use futures::future;
use log::LevelFilter;
use std::error::Error;
use std::sync::{Arc, Mutex};
use syslog::{BasicLogger, Facility, Formatter3164};

use bt_topshim::{btif::get_btinterface, topstack};
use btstack::{
    bluetooth::{get_bt_dispatcher, Bluetooth, IBluetooth},
    bluetooth_gatt::BluetoothGatt,
    bluetooth_media::BluetoothMedia,
    Stack,
};
use dbus_projection::DisconnectWatcher;

mod dbus_arg;
mod iface_bluetooth;
mod iface_bluetooth_gatt;
mod iface_bluetooth_media;

const DBUS_SERVICE_NAME: &str = "org.chromium.bluetooth";

/// Check command line arguments for target hci adapter (--hci=N). If no adapter
/// is set, default to 0.
fn get_adapter_index(args: &Vec<String>) -> i32 {
    for arg in args {
        if arg.starts_with("--hci=") {
            let num = (&arg[6..]).parse::<i32>();
            if num.is_ok() {
                return num.unwrap();
            }
        }
    }

    0
}

fn make_object_name(idx: i32, name: &str) -> String {
    String::from(format!("/org/chromium/bluetooth/hci{}/{}", idx, name))
}

/// Runs the Bluetooth daemon serving D-Bus IPC.
fn main() -> Result<(), Box<dyn Error>> {
    let formatter = Formatter3164 {
        facility: Facility::LOG_USER,
        hostname: None,
        process: "btadapterd".into(),
        pid: 0,
    };

    let logger = syslog::unix(formatter).expect("could not connect to syslog");
    let _ = log::set_boxed_logger(Box::new(BasicLogger::new(logger)))
        .map(|()| log::set_max_level(LevelFilter::Info));

    let (tx, rx) = Stack::create_channel();

    let intf = Arc::new(Mutex::new(get_btinterface().unwrap()));
    let bluetooth_gatt = Arc::new(Mutex::new(Box::new(BluetoothGatt::new(intf.clone()))));
    let bluetooth_media =
        Arc::new(Mutex::new(Box::new(BluetoothMedia::new(tx.clone(), intf.clone()))));
    let bluetooth = Arc::new(Mutex::new(Box::new(Bluetooth::new(
        tx.clone(),
        intf.clone(),
        bluetooth_media.clone(),
    ))));

    // Args don't include arg[0] which is the binary name
    let all_args = std::env::args().collect::<Vec<String>>();
    let args = all_args[1..].to_vec();

    let adapter_index = get_adapter_index(&args);

    // Hold locks and initialize all interfaces.
    {
        intf.lock().unwrap().initialize(get_bt_dispatcher(tx.clone()), args);

        let mut bluetooth = bluetooth.lock().unwrap();
        bluetooth.init_profiles();
        bluetooth.enable();

        bluetooth_gatt.lock().unwrap().init_profiles(tx.clone());
    }

    topstack::get_runtime().block_on(async {
        // Connect to D-Bus system bus.
        let (resource, conn) = connection::new_system_sync()?;

        // The `resource` is a task that should be spawned onto a tokio compatible
        // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus.
        tokio::spawn(async {
            let err = resource.await;
            panic!("Lost connection to D-Bus: {}", err);
        });

        // Request a service name and quit if not able to.
        conn.request_name(DBUS_SERVICE_NAME, false, true, false).await?;

        // Prepare D-Bus interfaces.
        let mut cr = Crossroads::new();
        cr.set_async_support(Some((
            conn.clone(),
            Box::new(|x| {
                tokio::spawn(x);
            }),
        )));

        // Run the stack main dispatch loop.
        topstack::get_runtime().spawn(Stack::dispatch(
            rx,
            bluetooth.clone(),
            bluetooth_gatt.clone(),
            bluetooth_media.clone(),
        ));

        // Set up the disconnect watcher to monitor client disconnects.
        let disconnect_watcher = Arc::new(Mutex::new(DisconnectWatcher::new()));
        disconnect_watcher.lock().unwrap().setup_watch(conn.clone()).await;

        // Register D-Bus method handlers of IBluetooth.
        iface_bluetooth::export_bluetooth_dbus_obj(
            make_object_name(adapter_index, "adapter"),
            conn.clone(),
            &mut cr,
            bluetooth.clone(),
            disconnect_watcher.clone(),
        );
        // Register D-Bus method handlers of IBluetoothGatt.
        iface_bluetooth_gatt::export_bluetooth_gatt_dbus_obj(
            make_object_name(adapter_index, "gatt"),
            conn.clone(),
            &mut cr,
            bluetooth_gatt,
            disconnect_watcher.clone(),
        );

        iface_bluetooth_media::export_bluetooth_media_dbus_obj(
            make_object_name(adapter_index, "media"),
            conn.clone(),
            &mut cr,
            bluetooth_media,
            disconnect_watcher.clone(),
        );

        conn.start_receive(
            MatchRule::new_method_call(),
            Box::new(move |msg, conn| {
                cr.handle_message(msg, conn).unwrap();
                true
            }),
        );

        // Serve clients forever.
        future::pending::<()>().await;
        unreachable!()
    })
}

#[cfg(test)]
mod tests {
    use crate::get_adapter_index;

    #[test]
    fn device_index_parsed() {
        // A few failing cases
        assert_eq!(get_adapter_index(&vec! {}), 0);
        assert_eq!(get_adapter_index(&vec! {"--bar".to_string(), "--hci".to_string()}), 0);
        assert_eq!(get_adapter_index(&vec! {"--hci=foo".to_string()}), 0);
        assert_eq!(get_adapter_index(&vec! {"--hci=12t".to_string()}), 0);

        // Some passing cases
        assert_eq!(get_adapter_index(&vec! {"--hci=12".to_string()}), 12);
        assert_eq!(get_adapter_index(&vec! {"--hci=1".to_string(), "--hci=2".to_string()}), 1);
    }
}
