use std::collections::HashMap;
use std::fmt::{Display, Formatter, Result};
use std::sync::{Arc, Mutex};

use crate::callbacks::BtGattCallback;
use crate::ClientContext;
use crate::{console_red, console_yellow, print_error, print_info};
use bt_topshim::btif::BtTransport;
use btstack::bluetooth::{BluetoothDevice, IBluetooth};
use btstack::bluetooth_gatt::IBluetoothGatt;
use btstack::uuid::UuidHelper;
use manager_service::iface_bluetooth_manager::IBluetoothManager;

const INDENT_CHAR: &str = " ";
const BAR1_CHAR: &str = "=";
const BAR2_CHAR: &str = "-";
const MAX_MENU_CHAR_WIDTH: usize = 72;
const GATT_CLIENT_APP_UUID: &str = "12345678123456781234567812345678";

type CommandFunction = fn(&mut CommandHandler, &Vec<String>);

fn _noop(_handler: &mut CommandHandler, _args: &Vec<String>) {
    // Used so we can add options with no direct function
    // e.g. help and quit
}

pub struct CommandOption {
    description: String,
    function_pointer: CommandFunction,
}

/// Handles string command entered from command line.
pub(crate) struct CommandHandler {
    context: Arc<Mutex<ClientContext>>,
    command_options: HashMap<String, CommandOption>,
}

struct DisplayList<T>(Vec<T>);

impl<T: Display> Display for DisplayList<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        let _ = write!(f, "[\n");
        for item in self.0.iter() {
            let _ = write!(f, "  {}\n", item);
        }

        write!(f, "]")
    }
}

fn enforce_arg_len<F>(args: &Vec<String>, min_len: usize, msg: &str, mut action: F)
where
    F: FnMut(),
{
    if args.len() < min_len {
        println!("Usage: {}", msg);
    } else {
        action();
    }
}

fn wrap_help_text(text: &str, max: usize, indent: usize) -> String {
    let remaining_count = std::cmp::max(
        // real_max
        std::cmp::max(max, text.chars().count())
        // take away char count
         - text.chars().count()
        // take away real_indent
         - (
             if std::cmp::max(max, text.chars().count())- text.chars().count() > indent {
                 indent
             } else {
                 0
             }),
        0,
    );

    format!("|{}{}{}|", INDENT_CHAR.repeat(indent), text, INDENT_CHAR.repeat(remaining_count))
}

// This should be called during the constructor in order to populate the command option map
fn build_commands() -> HashMap<String, CommandOption> {
    let mut command_options = HashMap::<String, CommandOption>::new();
    command_options.insert(
        String::from("adapter"),
        CommandOption {
            description: String::from(
                "Enable/Disable/Show default bluetooth adapter. (e.g. adapter enable)",
            ),
            function_pointer: CommandHandler::cmd_adapter,
        },
    );
    command_options.insert(
        String::from("bond"),
        CommandOption {
            description: String::from("Creates a bond with a device."),
            function_pointer: CommandHandler::cmd_bond,
        },
    );
    command_options.insert(
        String::from("device"),
        CommandOption {
            description: String::from("Take action on a remote device. (i.e. info)"),
            function_pointer: CommandHandler::cmd_device,
        },
    );
    command_options.insert(
        String::from("discovery"),
        CommandOption {
            description: String::from("Start and stop device discovery. (e.g. discovery start)"),
            function_pointer: CommandHandler::cmd_discovery,
        },
    );
    command_options.insert(
        String::from("floss"),
        CommandOption {
            description: String::from("Enable or disable Floss for dogfood."),
            function_pointer: CommandHandler::cmd_floss,
        },
    );
    command_options.insert(
        String::from("gatt"),
        CommandOption {
            description: String::from("GATT tools"),
            function_pointer: CommandHandler::cmd_gatt,
        },
    );
    command_options.insert(
        String::from("get-address"),
        CommandOption {
            description: String::from("Gets the local device address."),
            function_pointer: CommandHandler::cmd_get_address,
        },
    );
    command_options.insert(
        String::from("help"),
        CommandOption {
            description: String::from("Shows this menu."),
            function_pointer: CommandHandler::cmd_help,
        },
    );
    command_options.insert(
        String::from("list"),
        CommandOption {
            description: String::from(
                "List bonded or found remote devices. Use: list <bonded|found>",
            ),
            function_pointer: CommandHandler::cmd_list_devices,
        },
    );
    command_options.insert(
        String::from("quit"),
        CommandOption {
            description: String::from("Quit out of the interactive shell."),
            function_pointer: _noop,
        },
    );
    command_options
}

impl CommandHandler {
    /// Creates a new CommandHandler.
    pub fn new(context: Arc<Mutex<ClientContext>>) -> CommandHandler {
        CommandHandler { context, command_options: build_commands() }
    }

    /// Entry point for command and arguments
    pub fn process_cmd_line(&mut self, command: &String, args: &Vec<String>) {
        // Ignore empty line
        match &command[0..] {
            "" => {}
            _ => match self.command_options.get(command) {
                Some(cmd) => (cmd.function_pointer)(self, &args),
                None => {
                    println!("'{}' is an invalid command!", command);
                    self.cmd_help(&args);
                }
            },
        };
    }

    //  Common message for when the adapter isn't ready
    fn adapter_not_ready(&self) {
        let adapter_idx = self.context.lock().unwrap().default_adapter;
        print_error!(
            "Default adapter {} is not enabled. Enable the adapter before using this command.",
            adapter_idx
        );
    }

    fn cmd_help(&mut self, args: &Vec<String>) {
        if args.len() > 0 {
            match self.command_options.get(&args[0]) {
                Some(cmd) => {
                    println!(
                        "\n{}{}\n{}{}\n",
                        INDENT_CHAR.repeat(4),
                        args[0],
                        INDENT_CHAR.repeat(8),
                        cmd.description
                    );
                }
                None => {
                    println!("'{}' is an invalid command!", args[0]);
                    self.cmd_help(&vec![]);
                }
            }
        } else {
            // Build equals bar and Shave off sides
            let equal_bar = format!(" {} ", BAR1_CHAR.repeat(MAX_MENU_CHAR_WIDTH));

            // Build empty bar and Shave off sides
            let empty_bar = format!("|{}|", INDENT_CHAR.repeat(MAX_MENU_CHAR_WIDTH));

            // Header
            println!(
                "\n{}\n{}\n{}\n{}",
                equal_bar,
                wrap_help_text("Help Menu", MAX_MENU_CHAR_WIDTH, 2),
                // Minus bar
                format!("+{}+", BAR2_CHAR.repeat(MAX_MENU_CHAR_WIDTH)),
                empty_bar
            );

            // Print commands
            for (key, val) in self.command_options.iter() {
                println!(
                    "{}\n{}\n{}",
                    wrap_help_text(&key, MAX_MENU_CHAR_WIDTH, 4),
                    wrap_help_text(&val.description, MAX_MENU_CHAR_WIDTH, 8),
                    empty_bar
                );
            }

            // Footer
            println!("{}\n{}", empty_bar, equal_bar);
        }
    }

    fn cmd_adapter(&mut self, args: &Vec<String>) {
        let default_adapter = self.context.lock().unwrap().default_adapter;
        enforce_arg_len(args, 1, "adapter <enable|disable|show>", || match &args[0][0..] {
            "enable" => {
                self.context.lock().unwrap().manager_dbus.start(default_adapter);
            }
            "disable" => {
                self.context.lock().unwrap().manager_dbus.stop(default_adapter);
            }
            "show" => {
                if !self.context.lock().unwrap().manager_dbus.get_floss_enabled() {
                    println!("Floss is not enabled. First run, `floss enable`");
                    return;
                }

                let enabled = self.context.lock().unwrap().enabled;
                let address = match self.context.lock().unwrap().adapter_address.as_ref() {
                    Some(x) => x.clone(),
                    None => String::from(""),
                };
                let name = self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().get_name();
                let uuids = self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().get_uuids();
                print_info!("Address: {}", address);
                print_info!("Name: {}", name);
                print_info!("State: {}", if enabled { "enabled" } else { "disabled" });
                print_info!(
                    "Uuids: {}",
                    DisplayList(
                        uuids.iter().map(|&x| UuidHelper::to_string(&x)).collect::<Vec<String>>()
                    )
                );
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

    fn cmd_get_address(&mut self, _args: &Vec<String>) {
        if !self.context.lock().unwrap().adapter_ready {
            self.adapter_not_ready();
            return;
        }

        let address = self.context.lock().unwrap().update_adapter_address();
        print_info!("Local address = {}", &address);
    }

    fn cmd_discovery(&mut self, args: &Vec<String>) {
        if !self.context.lock().unwrap().adapter_ready {
            self.adapter_not_ready();
            return;
        }

        enforce_arg_len(args, 1, "discovery <start|stop>", || match &args[0][0..] {
            "start" => {
                self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().start_discovery();
            }
            "stop" => {
                self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().cancel_discovery();
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

    fn cmd_bond(&mut self, args: &Vec<String>) {
        if !self.context.lock().unwrap().adapter_ready {
            self.adapter_not_ready();
            return;
        }

        enforce_arg_len(args, 2, "bond <add|remove|cancel> <address>", || match &args[0][0..] {
            "add" => {
                let device = BluetoothDevice {
                    address: String::from(&args[1]),
                    name: String::from("Classic Device"),
                };

                let bonding_attempt =
                    &self.context.lock().unwrap().bonding_attempt.as_ref().cloned();

                if bonding_attempt.is_some() {
                    print_info!(
                        "Already bonding [{}]. Cancel bonding first.",
                        bonding_attempt.as_ref().unwrap().address,
                    );
                    return;
                }

                let success = self
                    .context
                    .lock()
                    .unwrap()
                    .adapter_dbus
                    .as_ref()
                    .unwrap()
                    .create_bond(device.clone(), BtTransport::Auto);

                if success {
                    self.context.lock().unwrap().bonding_attempt = Some(device);
                }
            }
            "remove" => {
                let device = BluetoothDevice {
                    address: String::from(&args[1]),
                    name: String::from("Classic Device"),
                };

                self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().remove_bond(device);
            }
            "cancel" => {
                let device = BluetoothDevice {
                    address: String::from(&args[1]),
                    name: String::from("Classic Device"),
                };

                self.context
                    .lock()
                    .unwrap()
                    .adapter_dbus
                    .as_ref()
                    .unwrap()
                    .cancel_bond_process(device);
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

    fn cmd_device(&mut self, args: &Vec<String>) {
        if !self.context.lock().unwrap().adapter_ready {
            self.adapter_not_ready();
            return;
        }

        enforce_arg_len(args, 2, "device <connect|disconnect|info> <address>", || {
            match &args[0][0..] {
                "connect" => {
                    let device = BluetoothDevice {
                        address: String::from(&args[1]),
                        name: String::from("Classic Device"),
                    };

                    let success = self
                        .context
                        .lock()
                        .unwrap()
                        .adapter_dbus
                        .as_ref()
                        .unwrap()
                        .connect_all_enabled_profiles(device.clone());

                    if success {
                        println!("Connecting to {}", &device.address);
                    } else {
                        println!("Can't connect to {}", &device.address);
                    }
                }
                "disconnect" => {
                    let device = BluetoothDevice {
                        address: String::from(&args[1]),
                        name: String::from("Classic Device"),
                    };

                    let success = self
                        .context
                        .lock()
                        .unwrap()
                        .adapter_dbus
                        .as_ref()
                        .unwrap()
                        .disconnect_all_enabled_profiles(device.clone());

                    if success {
                        println!("Disconnecting from {}", &device.address);
                    } else {
                        println!("Can't disconnect from {}", &device.address);
                    }
                }
                "info" => {
                    let device = BluetoothDevice {
                        address: String::from(&args[1]),
                        name: String::from("Classic Device"),
                    };

                    let (bonded, connected, uuids) = {
                        let ctx = self.context.lock().unwrap();
                        let adapter = ctx.adapter_dbus.as_ref().unwrap();

                        let bonded = adapter.get_bond_state(device.clone());
                        let connected = adapter.get_connection_state(device.clone());
                        let uuids = adapter.get_remote_uuids(device.clone());

                        (bonded, connected, uuids)
                    };

                    print_info!("Address: {}", &device.address);
                    print_info!("Bonded: {}", bonded);
                    print_info!("Connected: {}", connected);
                    print_info!(
                        "Uuids: {}",
                        DisplayList(
                            uuids
                                .iter()
                                .map(|&x| UuidHelper::to_string(&x))
                                .collect::<Vec<String>>()
                        )
                    );
                }
                _ => {
                    println!("Invalid argument '{}'", args[0]);
                }
            }
        });
    }

    fn cmd_floss(&mut self, args: &Vec<String>) {
        enforce_arg_len(args, 1, "floss <enable|disable>", || match &args[0][0..] {
            "enable" => {
                self.context.lock().unwrap().manager_dbus.set_floss_enabled(true);
            }
            "disable" => {
                self.context.lock().unwrap().manager_dbus.set_floss_enabled(false);
            }
            "show" => {
                print_info!(
                    "Floss enabled: {}",
                    self.context.lock().unwrap().manager_dbus.get_floss_enabled()
                );
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

    fn cmd_gatt(&mut self, args: &Vec<String>) {
        if !self.context.lock().unwrap().adapter_ready {
            self.adapter_not_ready();
            return;
        }

        enforce_arg_len(args, 1, "gatt <commands>", || match &args[0][0..] {
            "register-client" => {
                self.context.lock().unwrap().gatt_dbus.as_mut().unwrap().register_client(
                    String::from(GATT_CLIENT_APP_UUID),
                    Box::new(BtGattCallback::new(
                        String::from("/org/chromium/bluetooth/client/bluetooth_gatt_callback"),
                        self.context.clone(),
                    )),
                    false,
                );
            }
            "client-connect" => {
                if args.len() < 2 {
                    println!("usage: gatt client-connect <addr>");
                    return;
                }

                let client_id = self.context.lock().unwrap().gatt_client_id;
                if client_id.is_none() {
                    println!("GATT client is not yet registered.");
                    return;
                }

                let addr = String::from(&args[1]);
                self.context.lock().unwrap().gatt_dbus.as_ref().unwrap().client_connect(
                    client_id.unwrap(),
                    addr,
                    false,
                    2,
                    false,
                    1,
                );
            }
            "client-read-phy" => {
                if args.len() < 2 {
                    println!("usage: gatt client-read-phy <addr>");
                    return;
                }

                let client_id = self.context.lock().unwrap().gatt_client_id;
                if client_id.is_none() {
                    println!("GATT client is not yet registered.");
                    return;
                }

                let addr = String::from(&args[1]);
                self.context
                    .lock()
                    .unwrap()
                    .gatt_dbus
                    .as_mut()
                    .unwrap()
                    .client_read_phy(client_id.unwrap(), addr);
            }
            "client-discover-services" => {
                if args.len() < 2 {
                    println!("usage: gatt client-discover-services <addr>");
                    return;
                }

                let client_id = self.context.lock().unwrap().gatt_client_id;
                if client_id.is_none() {
                    println!("GATT client is not yet registered.");
                    return;
                }

                let addr = String::from(&args[1]);
                self.context
                    .lock()
                    .unwrap()
                    .gatt_dbus
                    .as_ref()
                    .unwrap()
                    .discover_services(client_id.unwrap(), addr);
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }

    /// Get the list of currently supported commands
    pub fn get_command_list(&self) -> Vec<String> {
        self.command_options.keys().map(|key| String::from(key)).collect::<Vec<String>>()
    }

    fn cmd_list_devices(&mut self, args: &Vec<String>) {
        if !self.context.lock().unwrap().adapter_ready {
            self.adapter_not_ready();
            return;
        }

        enforce_arg_len(args, 1, "list <bonded|found>", || match &args[0][0..] {
            "bonded" => {
                print_info!("Known bonded devices:");
                let devices = self
                    .context
                    .lock()
                    .unwrap()
                    .adapter_dbus
                    .as_ref()
                    .unwrap()
                    .get_bonded_devices();
                for device in devices.iter() {
                    print_info!("[{:17}] {}", device.address, device.name);
                }
            }
            "found" => {
                print_info!("Devices found in most recent discovery session:");
                for (key, val) in self.context.lock().unwrap().found_devices.iter() {
                    print_info!("[{:17}] {}", key, val.name);
                }
            }
            _ => {
                println!("Invalid argument '{}'", args[0]);
            }
        });
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_wrap_help_text() {
        let text = "hello";
        let text_len = text.chars().count();
        // ensure no overflow
        assert_eq!(format!("|{}|", text), wrap_help_text(text, 4, 0));
        assert_eq!(format!("|{}|", text), wrap_help_text(text, 5, 0));
        assert_eq!(format!("|{}{}|", text, " "), wrap_help_text(text, 6, 0));
        assert_eq!(format!("|{}{}|", text, " ".repeat(2)), wrap_help_text(text, 7, 0));
        assert_eq!(
            format!("|{}{}|", text, " ".repeat(100 - text_len)),
            wrap_help_text(text, 100, 0)
        );
        assert_eq!(format!("|{}{}|", " ", text), wrap_help_text(text, 4, 1));
        assert_eq!(format!("|{}{}|", " ".repeat(2), text), wrap_help_text(text, 5, 2));
        assert_eq!(format!("|{}{}{}|", " ".repeat(3), text, " "), wrap_help_text(text, 6, 3));
        assert_eq!(
            format!("|{}{}{}|", " ".repeat(4), text, " ".repeat(7 - text_len)),
            wrap_help_text(text, 7, 4)
        );
        assert_eq!(format!("|{}{}|", " ".repeat(9), text), wrap_help_text(text, 4, 9));
        assert_eq!(format!("|{}{}|", " ".repeat(10), text), wrap_help_text(text, 3, 10));
        assert_eq!(format!("|{}{}|", " ".repeat(11), text), wrap_help_text(text, 2, 11));
        assert_eq!(format!("|{}{}|", " ".repeat(12), text), wrap_help_text(text, 1, 12));
        assert_eq!("||", wrap_help_text("", 0, 0));
        assert_eq!("| |", wrap_help_text("", 1, 0));
        assert_eq!("|  |", wrap_help_text("", 1, 1));
        assert_eq!("| |", wrap_help_text("", 0, 1));
    }

    #[test]
    fn test_enforce_arg_len() {
        // With min arg set and min arg supplied
        let args: &Vec<String> = &vec![String::from("arg")];
        let mut i: usize = 0;
        enforce_arg_len(args, 1, "help text", || {
            i = 1;
        });
        assert_eq!(1, i);

        // With no min arg set and with arg supplied
        i = 0;
        enforce_arg_len(args, 0, "help text", || {
            i = 1;
        });
        assert_eq!(1, i);

        // With min arg set and no min arg supplied
        let args: &Vec<String> = &vec![];
        i = 0;
        enforce_arg_len(args, 1, "help text", || {
            i = 1;
        });
        assert_eq!(0, i);

        // With no min arg set and no arg supplied
        i = 0;
        enforce_arg_len(args, 0, "help text", || {
            i = 1;
        });
        assert_eq!(1, i);
    }
}
