// Copyright 2018 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.

#![recursion_limit = "512"]

use anyhow::{format_err, Context as _, Error};
use async_helpers::hanging_get::asynchronous as hanging_get;
use fidl::endpoints::{ControlHandle, DiscoverableProtocolMarker, ProtocolMarker};
use fidl_fuchsia_bluetooth::Appearance;
use fidl_fuchsia_bluetooth_bredr::ProfileMarker;
use fidl_fuchsia_bluetooth_gatt::Server_Marker;
use fidl_fuchsia_bluetooth_gatt2::{LocalServiceRequest, Server_Marker as Server_Marker2};
use fidl_fuchsia_bluetooth_host::{ReceiverRequest, ReceiverRequestStream};
use fidl_fuchsia_bluetooth_le::{CentralMarker, PeripheralMarker};
use fidl_fuchsia_device::NameProviderMarker;
use fuchsia_async as fasync;
use fuchsia_component::{client::connect_to_protocol, server::ServiceFs};
use futures::channel::mpsc;
use futures::future::BoxFuture;
use futures::{try_join, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
use std::collections::HashMap;
use tracing::{error, info, warn};

use crate::{
    generic_access_service::GenericAccessService,
    host_dispatcher::{HostDispatcher, HostService, HostService::*},
    services::host_watcher,
    watch_peers::PeerWatcher,
};

mod build_config;
mod generic_access_service;
mod host_device;
mod host_dispatcher;
mod services;
mod store;
#[cfg(test)]
mod test;
mod types;
mod watch_peers;

const BT_GAP_COMPONENT_ID: &'static str = "bt-gap";

#[fuchsia::main(logging_tags = ["bt-gap"])]
async fn main() -> Result<(), Error> {
    info!("Starting bt-gap...");
    let bt_gap = BtGap::init().await.context("Error starting bt-gap").map_err(|e| {
        error!("{:?}", e);
        e
    })?;

    bt_gap.run().await.context("Error running bt-gap").map_err(|e| {
        error!("{:?}", e);
        e
    })
}

/// Returns the device host name that we assign as the local Bluetooth device name by default.
async fn get_host_name() -> types::Result<String> {
    // Obtain the local device name to assign it as the default Bluetooth name,
    let name_provider = connect_to_protocol::<NameProviderMarker>()?;
    name_provider
        .get_device_name()
        .await?
        .map_err(|e| format_err!("failed to obtain host name: {:?}", e).into())
}

fn host_service_handler(
    dispatcher: &HostDispatcher,
    service_name: &'static str,
    service: HostService,
) -> impl FnMut(fuchsia_zircon::Channel) -> Option<()> {
    let dispatcher = dispatcher.clone();
    move |chan| {
        info!("Connecting {} to Host Device", service_name);
        fasync::Task::spawn(dispatcher.clone().request_host_service(chan, service)).detach();
        None
    }
}

async fn run_receiver_server(
    hd: HostDispatcher,
    mut stream: ReceiverRequestStream,
) -> Result<(), Error> {
    info!("Receiver server task started");

    let hd_ref = &hd;

    while let Some(request) = stream.try_next().await? {
        match request {
            ReceiverRequest::AddHost { request, control_handle } => {
                if let Err(e) = hd_ref.add_host_component(request.into_proxy()?).await {
                    info!("Error while adding host to bt-gap: {e:?}");
                    control_handle.shutdown();
                }
            }
            ReceiverRequest::_UnknownMethod { ordinal, .. } => {
                println!("Received an unknown method with ordinal {ordinal}");
            }
        }
    }
    Ok(())
}

/// The constituent parts of the bt-gap application.
struct BtGap {
    hd: HostDispatcher,
    inspect: fuchsia_inspect::Inspector,
    /// The generic access service requests
    gas_requests: mpsc::Receiver<LocalServiceRequest>,
    run_watch_peers: BoxFuture<'static, Result<(), Error>>,
    run_watch_hosts: BoxFuture<'static, Result<(), Error>>,
}

impl BtGap {
    /// Initialize bt-gap, in particular creating the core HostDispatcher object
    async fn init() -> Result<Self, Error> {
        info!("Initializing bt-gap...");
        let inspect = fuchsia_inspect::Inspector::default();
        let stash_inspect = inspect.root().create_child("persistent");
        info!("Initializing data store from Stash...");
        let stash = store::stash::init_stash(BT_GAP_COMPONENT_ID, stash_inspect)
            .await
            .context("Error initializing Stash service")?;
        info!("Data store initialized successfully");

        let (gas_channel_sender, gas_requests) = mpsc::channel(0);

        // Initialize a HangingGetBroker to process watch_peers requests
        let watch_peers_broker = hanging_get::HangingGetBroker::new(
            HashMap::new(),
            PeerWatcher::observe,
            hanging_get::DEFAULT_CHANNEL_SIZE,
        );
        let watch_peers_publisher = watch_peers_broker.new_publisher();
        let watch_peers_registrar = watch_peers_broker.new_registrar();

        // Initialize a HangingGetBroker to process watch_hosts requests
        let watch_hosts_broker = hanging_get::HangingGetBroker::new(
            Vec::new(),
            host_watcher::observe_hosts,
            hanging_get::DEFAULT_CHANNEL_SIZE,
        );
        let watch_hosts_publisher = watch_hosts_broker.new_publisher();
        let watch_hosts_registrar = watch_hosts_broker.new_registrar();

        // Process the watch_peers broker in the background
        let run_watch_peers = watch_peers_broker
            .run()
            .map(|()| Err::<(), Error>(format_err!("WatchPeers broker terminated unexpectedly")))
            .boxed();
        // Process the watch_hosts broker in the background
        let run_watch_hosts = watch_hosts_broker
            .run()
            .map(|()| Err::<(), Error>(format_err!("WatchHosts broker terminated unexpectedly")))
            .boxed();

        let hd = HostDispatcher::new(
            Appearance::Display,
            stash,
            inspect.root().create_child("system"),
            gas_channel_sender,
            watch_peers_publisher,
            watch_peers_registrar,
            watch_hosts_publisher,
            watch_hosts_registrar,
        );

        info!("bt-gap successfully initialized.");
        Ok(BtGap { hd, inspect, gas_requests, run_watch_peers, run_watch_hosts })
    }

    /// Run continuous tasks that are expected to live until bt-gap terminates
    async fn run(self) -> Result<(), Error> {
        let set_local_name = {
            let hd = self.hd.clone();
            async move {
                info!("Obtaining system host name...");
                if let Err(e) = get_host_name()
                    .and_then(|name| hd.set_name(name, host_dispatcher::NameReplace::Keep))
                    .await
                {
                    warn!("Error setting Bluetooth host name from system: {:?}", e);
                }
                Ok(())
            }
        };

        let run_generic_access_service =
            GenericAccessService::build(&self.hd, self.gas_requests).run().map(|()| {
                Err::<(), Error>(format_err!("Generic Access Server terminated unexpectedly"))
            });

        let serve_fidl = serve_fidl(self.hd.clone(), self.inspect);

        try_join!(
            set_local_name,
            serve_fidl,
            run_generic_access_service,
            self.run_watch_peers,
            self.run_watch_hosts,
        )
        .map(|((), (), (), (), ())| ())
    }
}

/// Serve the FIDL protocols offered by bt-gap
async fn serve_fidl(hd: HostDispatcher, inspect: fuchsia_inspect::Inspector) -> Result<(), Error> {
    let mut fs = ServiceFs::new();

    // serve bt-gap inspect VMO
    let _inspect_server_task =
        inspect_runtime::publish(&inspect, inspect_runtime::PublishOptions::default());

    let _ = fs
        .dir("svc")
        .add_service_at(
            CentralMarker::PROTOCOL_NAME,
            host_service_handler(&hd, CentralMarker::DEBUG_NAME, LeCentral),
        )
        .add_service_at(
            PeripheralMarker::PROTOCOL_NAME,
            host_service_handler(&hd, PeripheralMarker::DEBUG_NAME, LePeripheral),
        )
        .add_service_at(
            Server_Marker::PROTOCOL_NAME,
            host_service_handler(&hd, Server_Marker::DEBUG_NAME, LeGatt),
        )
        .add_service_at(
            Server_Marker2::PROTOCOL_NAME,
            host_service_handler(&hd, Server_Marker2::DEBUG_NAME, LeGatt2),
        )
        .add_service_at(
            ProfileMarker::PROTOCOL_NAME,
            host_service_handler(&hd, ProfileMarker::PROTOCOL_NAME, Profile),
        )
        // TODO(https://fxbug.dev/42088102) - according fuchsia.bluetooth.sys/bootstrap.fidl, the bootstrap service should
        // only be available before initialization, and only allow a single commit before becoming
        // unservicable. This behavior interacts with parts of Bluetooth lifecycle and component
        // framework design that are not yet complete. For now, we provide the service to whomever
        // asks, whenever, but clients should not rely on this. The implementation will change once
        // we have a better solution.
        .add_fidl_service(|request_stream| {
            let hd = hd.clone();
            fasync::Task::spawn(
                services::bootstrap::run(hd, request_stream)
                    .unwrap_or_else(|e| warn!("Bootstrap service failed: {:?}", e)),
            )
            .detach();
        })
        .add_fidl_service(|request_stream| {
            let hd = hd.clone();
            fasync::Task::spawn(
                services::access::run(hd, request_stream)
                    .unwrap_or_else(|e| warn!("Access service failed: {:?}", e)),
            )
            .detach();
        })
        .add_fidl_service(|request_stream| {
            let hd = hd.clone();
            fasync::Task::spawn(
                services::configuration::run(hd, request_stream)
                    .unwrap_or_else(|e| warn!("Configuration service failed: {:?}", e)),
            )
            .detach();
        })
        .add_fidl_service(|request_stream| {
            let hd = hd.clone();
            fasync::Task::spawn(
                services::host_watcher::run(hd, request_stream)
                    .unwrap_or_else(|e| warn!("HostWatcher service failed: {:?}", e)),
            )
            .detach();
        })
        .add_fidl_service(|request_stream| {
            let hd = hd.clone();
            fasync::Task::spawn(
                services::pairing::run(hd, request_stream)
                    .unwrap_or_else(|e| warn!("Pairing service failed: {:?}", e)),
            )
            .detach();
        })
        .add_fidl_service(|request_stream| {
            let hd = hd.clone();
            fasync::Task::spawn(
                run_receiver_server(hd, request_stream)
                    .unwrap_or_else(|e| warn!("Receiver service failed: {:?}", e)),
            )
            .detach();
        });
    let _ = fs.take_and_serve_directory_handle()?;
    fs.collect::<()>().await;
    Ok(())
}
