// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use anyhow::Error;
use async_utils::hanging_get::client::HangingGetStream;
use fidl::endpoints::RequestStream;
use fidl_fuchsia_bluetooth::PeerId;
use fidl_fuchsia_bluetooth_sys::{
    AccessMarker, AccessProxy, BondableMode, HostInfo, HostWatcherMarker, InputCapability,
    OutputCapability, PairingDelegateMarker, PairingDelegateRequest, PairingDelegateRequestStream,
    PairingMethod, PairingOptions, PairingSecurityLevel, Peer, ProcedureTokenProxy, TechnologyType,
};
use fuchsia_async::{self as fasync, DurationExt, TimeoutExt};
use fuchsia_bluetooth::types::Address;
use fuchsia_component as component;
use fuchsia_syslog::macros::{fx_log_err, fx_log_info};
use fuchsia_zircon::{self as zx, DurationNum};

use parking_lot::RwLock;
use std::collections::HashMap;

use crate::bluetooth::types::SerializablePeer;
use crate::common_utils::common::macros::{fx_err_and_bail, with_line};

use futures::channel::mpsc;
use futures::stream::StreamExt;

use derivative::Derivative;

static ERR_NO_ACCESS_PROXY_DETECTED: &'static str = "No Bluetooth Access Proxy detected.";

#[derive(Derivative)]
#[derivative(Debug)]
struct InnerBluetoothSysFacade {
    /// The current Bluetooth Access Interface Proxy
    access_proxy: Option<AccessProxy>,

    /// The MPSC Sender object for sending the pin to the pairing delegate.
    client_pin_sender: Option<mpsc::Sender<String>>,

    /// The MPSC Receiver object for sending the pin out from the pairing delegate.
    client_pin_receiver: Option<mpsc::Receiver<String>>,

    /// Discovered device list
    discovered_device_list: HashMap<u64, SerializablePeer>,

    /// Discoverable token
    discoverable_token: Option<ProcedureTokenProxy>,

    /// Discovery token
    discovery_token: Option<ProcedureTokenProxy>,

    /// Peer Watcher Stream for incomming and dropped peers
    #[derivative(Debug = "ignore")]
    peer_watcher_stream: Option<HangingGetStream<(Vec<Peer>, Vec<PeerId>)>>,

    /// Host Watcher Stream for watching hosts
    #[derivative(Debug = "ignore")]
    host_watcher_stream: Option<HangingGetStream<Vec<HostInfo>>>,

    /// Current active BT address
    active_bt_address: Option<String>,
}

#[derive(Debug)]
pub struct BluetoothSysFacade {
    inner: RwLock<InnerBluetoothSysFacade>,
}

/// Perform Bluetooth Access operations.
///
/// Note this object is shared among all threads created by server.
impl BluetoothSysFacade {
    pub fn new() -> BluetoothSysFacade {
        BluetoothSysFacade {
            inner: RwLock::new(InnerBluetoothSysFacade {
                access_proxy: None,
                client_pin_sender: None,
                client_pin_receiver: None,
                discovered_device_list: HashMap::new(),
                discoverable_token: None,
                discovery_token: None,
                peer_watcher_stream: None,
                host_watcher_stream: None,
                active_bt_address: None,
            }),
        }
    }

    pub fn init_proxies(&self) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::init_proxies";
        let mut inner = self.inner.write();
        let proxy = match inner.access_proxy.clone() {
            Some(access_proxy) => {
                fx_log_info!(tag: &with_line!(tag), "Current access proxy: {:?}", access_proxy);
                Ok(access_proxy)
            }
            None => {
                fx_log_info!(tag: &with_line!(tag), "Setting new access proxy");
                let access_proxy = component::client::connect_to_service::<AccessMarker>();
                if let Err(err) = access_proxy {
                    fx_err_and_bail!(
                        &with_line!(tag),
                        format_err!("Failed to create access proxy: {:?}", err)
                    );
                }

                access_proxy
            }
        };

        let proxy = proxy.unwrap();
        inner.access_proxy = Some(proxy.clone());

        inner.peer_watcher_stream =
            Some(HangingGetStream::new(Box::new(move || Some(proxy.watch_peers()))));

        let host_watcher_proxy = match component::client::connect_to_service::<HostWatcherMarker>()
        {
            Ok(proxy) => proxy,
            Err(err) => fx_err_and_bail!(
                &with_line!(tag),
                format_err!("Failed to connect to HostWatcher: {}", err)
            ),
        };

        inner.host_watcher_stream =
            Some(HangingGetStream::new(Box::new(move || Some(host_watcher_proxy.watch()))));

        Ok(())
    }

    pub async fn monitor_pairing_delegate_request_stream(
        mut stream: PairingDelegateRequestStream,
        mut pin_receiver: mpsc::Receiver<String>,
        mut pin_sender: mpsc::Sender<String>,
    ) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::monitor_pairing_delegate_request_stream";
        while let Some(request) = stream.next().await {
            match request {
                Ok(r) => match r {
                    PairingDelegateRequest::OnPairingComplete {
                        id,
                        success,
                        control_handle: _,
                    } => {
                        fx_log_info!(
                            tag: &with_line!(tag),
                            "Pairing complete for peer (id: {}, status: {})",
                            id.value,
                            match success {
                                true => "Success",
                                false => "Failure",
                            }
                        );
                    }
                    PairingDelegateRequest::OnPairingRequest {
                        peer,
                        method,
                        displayed_passkey,
                        responder,
                    } => {
                        let _res = pin_sender.try_send(displayed_passkey.to_string());

                        let address = match &peer.address {
                            Some(address) => Address::from(address).to_string(),
                            None => "Unknown Address".to_string(),
                        };
                        fx_log_info!(
                            tag: &with_line!(tag),
                            "Pairing request from peer: {}",
                            match &peer.name {
                                Some(name) => format!("{} ({})", name, address),
                                None => address,
                            }
                        );
                        let consent = true;
                        let default_passkey = "000000".to_string();
                        let (confirm, entered_passkey) = match method {
                            PairingMethod::Consent => (consent, None),
                            PairingMethod::PasskeyComparison => (consent, None),
                            PairingMethod::PasskeyDisplay => {
                                fx_log_info!(
                                    "Passkey {:?} provided for 'Passkey Display`.",
                                    displayed_passkey
                                );
                                (true, None)
                            }
                            PairingMethod::PasskeyEntry => {
                                let timeout = 30.seconds(); // Spec defined timeout
                                let pin = match pin_receiver
                                    .next()
                                    .on_timeout(timeout.after_now(), || None)
                                    .await
                                {
                                    Some(p) => p,
                                    _ => {
                                        fx_log_err!(
                                            tag: &with_line!(tag),
                                            "No pairing pin found from remote host."
                                        );
                                        default_passkey
                                    }
                                };

                                (consent, Some(pin))
                            }
                        };
                        let _ = responder.send(
                            confirm,
                            match entered_passkey {
                                Some(passkey) => passkey.parse::<u32>().unwrap(),
                                None => 0u32,
                            },
                        );
                    }
                    PairingDelegateRequest::OnRemoteKeypress {
                        id,
                        keypress,
                        control_handle: _,
                    } => {
                        fx_log_info!(
                            tag: &with_line!(tag),
                            "Unhandled OnRemoteKeypress for Device: {} | {:?}",
                            id.value,
                            keypress
                        );
                    }
                },
                Err(r) => return Err(format_err!("Error during handling request stream: {:?}", r)),
            };
        }
        Ok(())
    }

    /// Starts the pairing delegate with I/O Capabilities as required inputs.
    ///
    /// # Arguments
    /// * `input` - A String representing the input capability.
    ///       Available values: NONE, CONFIRMATION, KEYBOARD
    /// * `output` - A String representing the output capability
    ///       Available values: NONE, DISPLAY
    pub async fn accept_pairing(&self, input: &str, output: &str) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::accept_pairing";
        let input_capability = match input {
            "NONE" => InputCapability::None,
            "CONFIRMATION" => InputCapability::Confirmation,
            "KEYBOARD" => InputCapability::Keyboard,
            _ => {
                fx_err_and_bail!(&with_line!(tag), format!("Invalid Input Capability {:?}", input))
            }
        };
        let output_capability = match output {
            "NONE" => OutputCapability::None,
            "DISPLAY" => OutputCapability::Display,
            _ => fx_err_and_bail!(
                &with_line!(tag),
                format!("Invalid Output Capability {:?}", output)
            ),
        };

        fx_log_info!(tag: &with_line!(tag), "Accepting pairing");
        let (delegate_local, delegate_remote) = zx::Channel::create()?;
        let delegate_local = fasync::Channel::from_channel(delegate_local)?;
        let delegate_ptr =
            fidl::endpoints::ClientEnd::<PairingDelegateMarker>::new(delegate_remote);
        let _result = match &self.inner.read().access_proxy {
            Some(p) => p.set_pairing_delegate(input_capability, output_capability, delegate_ptr),
            None => fx_err_and_bail!(&with_line!(tag), "No Bluetooth Access Proxy Set."),
        };
        let delegate_request_stream = PairingDelegateRequestStream::from_channel(delegate_local);

        let (sender, pin_receiver) = mpsc::channel(10);
        let (pin_sender, receiever) = mpsc::channel(10);
        let pairing_delegate_fut = BluetoothSysFacade::monitor_pairing_delegate_request_stream(
            delegate_request_stream,
            pin_receiver,
            pin_sender,
        );

        self.inner.write().client_pin_sender = Some(sender);
        self.inner.write().client_pin_receiver = Some(receiever);

        let fut = async {
            let result = pairing_delegate_fut.await;
            if let Err(err) = result {
                fx_log_err!(
                    tag: &with_line!("BluetoothSysFacade::accept_pairing"),
                    "Failed to create or monitor the pairing service delegate: {:?}",
                    err
                );
            }
        };
        fasync::Task::spawn(fut).detach();

        Ok(())
    }

    /// Sets an access proxy to use if one is not already in use.
    pub async fn init_access_proxy(&self) -> Result<(), Error> {
        self.init_proxies()
    }

    pub async fn input_pairing_pin(&self, pin: String) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::input_pairing_pin";
        match self.inner.read().client_pin_sender.clone() {
            Some(mut sender) => sender.try_send(pin)?,
            None => {
                let err_msg = "No sender setup for pairing delegate.".to_string();
                fx_err_and_bail!(&with_line!(tag), err_msg)
            }
        };
        Ok(())
    }

    pub async fn get_pairing_pin(&self) -> Result<String, Error> {
        let tag = "BluetoothSysFacade::get_pairing_pin";
        let pin = match &mut self.inner.write().client_pin_receiver {
            Some(receiever) => match receiever.try_next() {
                Ok(value) => match value {
                    Some(v) => v,
                    None => return Err(format_err!("Error getting pin from pairing delegate.")),
                },
                Err(_e) => {
                    let err_msg = "No pairing pin sent from the pairing delegate.".to_string();
                    fx_err_and_bail!(&with_line!(tag), err_msg)
                }
            },
            None => {
                let err_str = "No receiever setup for pairing delegate.".to_string();
                fx_log_err!(tag: &with_line!(tag), "{}", err_str);
                bail!(err_str)
            }
        };
        Ok(pin)
    }

    /// Sets the current access proxy to be discoverable.
    ///
    /// # Arguments
    /// * 'discoverable' - A bool object for setting Bluetooth device discoverable or not.
    pub async fn set_discoverable(&self, discoverable: bool) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::set_discoverable";

        if !discoverable {
            self.inner.write().discoverable_token = None;
        } else {
            let token = match &self.inner.read().access_proxy {
                Some(proxy) => {
                    let (token, token_server) = fidl::endpoints::create_proxy()?;
                    let resp = proxy.make_discoverable(token_server).await?;
                    if let Err(err) = resp {
                        let err_msg = format_err!("Error: {:?}", err);
                        fx_err_and_bail!(&with_line!(tag), err_msg)
                    }
                    token
                }
                None => fx_err_and_bail!(
                    &with_line!(tag),
                    format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
                ),
            };
            self.inner.write().discoverable_token = Some(token);
        }
        Ok(())
    }

    /// Sets the current access proxy name.
    ///
    /// # Arguments
    /// * 'name' - A String object representing the name to set.
    pub async fn set_name(&self, name: String) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::set_name";
        match &self.inner.read().access_proxy {
            Some(proxy) => {
                let resp = proxy.set_local_name(&name);
                if let Err(err) = resp {
                    let err_msg = format_err!("Error: {:?}", err);
                    fx_err_and_bail!(&with_line!(tag), err_msg)
                }
                Ok(())
            }
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
            ),
        }
    }

    /// Starts discovery on the Bluetooth Access Proxy.
    ///
    /// # Arguments
    /// * 'discovery' - A bool representing starting and stopping discovery.
    pub async fn start_discovery(&self, discovery: bool) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::start_discovery";
        if !discovery {
            self.inner.write().discovery_token = None;
            Ok(())
        } else {
            let token = match &self.inner.read().access_proxy {
                Some(proxy) => {
                    let (token, token_server) = fidl::endpoints::create_proxy()?;
                    let resp = proxy.start_discovery(token_server).await?;
                    if let Err(err) = resp {
                        let err_msg = format_err!("Error: {:?}", err);
                        fx_err_and_bail!(&with_line!(tag), err_msg)
                    }
                    token
                }
                None => fx_err_and_bail!(
                    &with_line!(tag),
                    format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
                ),
            };
            self.inner.write().discovery_token = Some(token);
            Ok(())
        }
    }

    /// Returns a hashmap of the known devices on the Bluetooth Access proxy.
    pub async fn get_known_remote_devices(&self) -> Result<HashMap<u64, SerializablePeer>, Error> {
        let tag = "BluetoothSysFacade::get_known_remote_devices";

        match &self.inner.read().discovery_token {
            Some(_) => (),
            None => return Ok(self.inner.read().discovered_device_list.clone()),
        };

        let default_return = self.inner.read().discovered_device_list.clone();

        let (discovered_devices, removed_peers) = match &mut self.inner.write().peer_watcher_stream
        {
            Some(stream) => {
                match stream.next().on_timeout(1.seconds().after_now(), || None).await {
                    Some(r) => match r {
                        Ok(d) => d,
                        Err(e) => fx_err_and_bail!(
                            &with_line!(tag),
                            format!("{:?}", format!("Peer Watcher Stream failed with: {:?}", e))
                        ),
                    },
                    None => return Ok(default_return),
                }
            }
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", "Peer Watcher Stream not available")
            ),
        };

        let serialized_peers_map: HashMap<u64, SerializablePeer> =
            discovered_devices.iter().map(|d| (d.id.unwrap().value, d.into())).collect();

        self.inner.write().discovered_device_list.extend(serialized_peers_map);

        let mut known_devices = self.inner.write().discovered_device_list.clone();
        for peer_id in removed_peers {
            if known_devices.contains_key(&peer_id.value) {
                fx_log_info!(tag: tag, "Peer {:?} removed.", peer_id);
                known_devices.remove(&peer_id.value);
            }
        }
        self.inner.write().discovered_device_list = known_devices;

        Ok(self.inner.read().discovered_device_list.clone())
    }

    /// Forgets (Unbonds) an input device ID.
    ///
    /// # Arguments
    /// * `id` - A u64 representing the device ID.
    pub async fn forget(&self, id: u64) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::forget";
        match &self.inner.read().access_proxy {
            Some(proxy) => {
                let resp = proxy.forget(&mut PeerId { value: id }).await?;
                if let Err(err) = resp {
                    let err_msg = format_err!("Error: {:?}", err);
                    fx_err_and_bail!(&with_line!(tag), err_msg)
                }
                Ok(())
            }
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
            ),
        }
    }

    /// Connects over BR/EDR to an input device ID.
    ///
    /// # Arguments
    /// * `id` - A u64 representing the device ID.
    pub async fn connect(&self, id: u64) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::connect";
        match &self.inner.read().access_proxy {
            Some(proxy) => {
                let resp = proxy.connect(&mut PeerId { value: id }).await?;
                if let Err(err) = resp {
                    let err_msg = format_err!("Error: {:?}", err);
                    fx_err_and_bail!(&with_line!(tag), err_msg)
                }
                Ok(())
            }
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
            ),
        }
    }

    /// Sends an outgoing pairing request over BR/EDR or LE to an input device ID.
    ///
    /// # Arguments
    /// * `id` - A u64 representing the device ID.
    /// * `pairing_security_level_value` - The security level required for this pairing request
    ///        represented as a u64. (Only for LE pairing)
    ///        Available Values
    ///        1 - ENCRYPTED: Encrypted without MITM protection (unauthenticated)
    ///        2 - AUTHENTICATED: Encrypted with MITM protection (authenticated).
    ///        None: Used for BR/EDR
    /// * `bondable` - A bool representing whether the pairing mode is bondable or not. None is
    ///        also accepted. False if non bondable, True if bondable.
    /// * `transport_value` - A u64 representing the transport type.
    ///        Available Values
    ///        1 - BREDR: Classic BR/EDR transport
    ///        2 - LE: Bluetooth Low Energy Transport
    pub async fn pair(
        &self,
        id: u64,
        pairing_security_level_value: Option<u64>,
        bondable: Option<bool>,
        transport_value: u64,
    ) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::pair";

        let pairing_security_level = match pairing_security_level_value {
            Some(value) => match value {
                1 => Some(PairingSecurityLevel::Encrypted),
                2 => Some(PairingSecurityLevel::Authenticated),
                _ => fx_err_and_bail!(
                    &with_line!(tag),
                    format!(
                        "Invalid pairing security level provided: {:?}",
                        pairing_security_level_value
                    )
                ),
            },
            None => None,
        };

        let transport = match transport_value {
            1 => TechnologyType::Classic,
            2 => TechnologyType::LowEnergy,
            _ => fx_err_and_bail!(
                &with_line!(tag),
                format!("Invalid transport provided: {:?}", transport_value)
            ),
        };

        let bondable_mode = match bondable {
            Some(v) => match v {
                false => BondableMode::NonBondable,
                true => BondableMode::Bondable,
            },
            None => BondableMode::Bondable,
        };

        let pairing_options = PairingOptions {
            le_security_level: pairing_security_level,
            bondable_mode: Some(bondable_mode),
            transport: Some(transport),
            ..PairingOptions::EMPTY
        };

        let proxy = match &self.inner.read().access_proxy {
            Some(p) => p.clone(),
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
            ),
        };
        let fut = async move {
            let result = proxy.pair(&mut PeerId { value: id }, pairing_options).await;
            if let Err(err) = result {
                fx_log_err!(
                    tag: &with_line!("BluetoothSysFacade::pair"),
                    "Failed to pair with: {:?}",
                    err
                );
            }
        };
        fasync::Task::spawn(fut).detach();
        Ok(())
    }

    /// Disconnects an active BR/EDR connection by input device ID.
    ///
    /// # Arguments
    /// * `id` - A u64 representing the device ID.
    pub async fn disconnect(&self, id: u64) -> Result<(), Error> {
        let tag = "BluetoothSysFacade::disconnect";
        match &self.inner.read().access_proxy {
            Some(proxy) => {
                let resp = proxy.disconnect(&mut PeerId { value: id }).await?;
                if let Err(err) = resp {
                    let err_msg = format_err!("Error: {:?}", err);
                    fx_err_and_bail!(&with_line!(tag), err_msg)
                }
                Ok(())
            }
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", ERR_NO_ACCESS_PROXY_DETECTED.to_string())
            ),
        }
    }

    /// Returns the current Active Adapter's Address.
    pub async fn get_active_adapter_address(&self) -> Result<String, Error> {
        let tag = "BluetoothSysFacade::get_active_adapter_address";

        let host_info_list = match &mut self.inner.write().host_watcher_stream {
            Some(stream) => {
                match stream.next().on_timeout(1.seconds().after_now(), || None).await {
                    Some(r) => match r {
                        Ok(d) => d,
                        Err(e) => fx_err_and_bail!(
                            &with_line!(tag),
                            format!("{:?}", format!("Host Watcher Stream failed with: {:?}", e))
                        ),
                    },
                    None => {
                        match &self.inner.read().active_bt_address {
                            Some(addr) => return Ok(addr.to_string()),
                            None => fx_err_and_bail!(
                                &with_line!(tag),
                                format!(
                                    "{:?}",
                                    "No active adapter - Timed out waiting for host_watcher_stream update."
                                )
                            ),
                        };
                    }
                }
            }
            None => fx_err_and_bail!(
                &with_line!(tag),
                format!("{:?}", "Host Watcher Stream not available")
            ),
        };

        for host in host_info_list {
            let host_active = host.active.unwrap();
            if host_active {
                match host.address {
                    Some(a) => {
                        self.inner.write().active_bt_address = Some(Address::from(a).to_string());
                        return Ok(Address::from(a).to_string());
                    }
                    None => fx_err_and_bail!(&with_line!(tag), "Host address not found."),
                }
            }
        }
        fx_err_and_bail!(&with_line!(tag), "No active host found.")
    }

    /// Cleans up objects in use.
    pub fn cleanup(&self) {
        let mut inner = self.inner.write();
        inner.access_proxy = None;
        inner.client_pin_sender = None;
        inner.client_pin_receiver = None;
        inner.discovered_device_list.clear();
        inner.discoverable_token = None;
        inner.discovery_token = None;
    }

    /// Prints useful information.
    pub fn print(&self) {
        let tag = "BluetoothSysFacade::print:";
        fx_log_info!(tag: &with_line!(tag), "access_proxy: {:?}", self.inner.read().access_proxy);
        fx_log_info!(
            tag: &with_line!(tag),
            "discovered_device_list: {:?}",
            self.inner.read().discovered_device_list
        );
    }
}
