// Copyright 2019 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::{format_err, Error};
use fidl::endpoints::{create_request_stream, Responder};
use fidl_fuchsia_bluetooth_gatt2 as gatt;
use fuchsia_bluetooth::types::Uuid;
use futures::{channel::mpsc, SinkExt, StreamExt};
use tracing::{info, warn};

use crate::host_dispatcher::HostDispatcher;

const GENERIC_ACCESS_SERVICE_UUID: Uuid = Uuid::new16(0x1800);
const GENERIC_ACCESS_DEVICE_NAME_UUID: Uuid = Uuid::new16(0x2A00);
const GENERIC_ACCESS_APPEARANCE_UUID: Uuid = Uuid::new16(0x2A01);
const GENERIC_ACCESS_DEVICE_NAME_ID: u64 = 0x2A00;
const GENERIC_ACCESS_APPEARANCE_ID: u64 = 0x2A01;

fn build_generic_access_service_info() -> gatt::ServiceInfo {
    // The spec says these characteristics should be readable, but optionally writeable. For
    // simplicity, we've disallowed them being peer-writeable. We enable access to these
    // characteristics with no security, as they are sent out freely during advertising anyway.
    let device_name_characteristic = gatt::Characteristic {
        handle: Some(gatt::Handle { value: GENERIC_ACCESS_DEVICE_NAME_ID }),
        type_: Some(GENERIC_ACCESS_DEVICE_NAME_UUID.into()),
        properties: Some(gatt::CharacteristicPropertyBits::READ),
        permissions: Some(gatt::AttributePermissions {
            read: Some(gatt::SecurityRequirements::default()),
            ..Default::default()
        }),
        ..Default::default()
    };

    let appearance_characteristic = gatt::Characteristic {
        handle: Some(gatt::Handle { value: GENERIC_ACCESS_APPEARANCE_ID }),
        type_: Some(GENERIC_ACCESS_APPEARANCE_UUID.into()),
        properties: Some(gatt::CharacteristicPropertyBits::READ),
        permissions: Some(gatt::AttributePermissions {
            read: Some(gatt::SecurityRequirements::default()),
            ..Default::default()
        }),
        ..Default::default()
    };

    gatt::ServiceInfo {
        // This value is ignored as this is a local-only service
        handle: Some(gatt::ServiceHandle { value: 0 }),
        // Secondary services are only rarely used and this is not one of those cases
        kind: Some(gatt::ServiceKind::Primary),
        type_: Some(GENERIC_ACCESS_SERVICE_UUID.into()),
        characteristics: Some(vec![device_name_characteristic, appearance_characteristic]),
        ..Default::default()
    }
}

/// A GasProxy forwards peer Generic Access Service requests received by a BT host to the local GAS
/// task. A GasProxy will be spawned as a task by HostDispatcher whenever a new host is detected.
/// Passing the requests through proxies is preferable to the  task maintaining host state so that
/// we can limit host state to one place, HostDispatcher. This will simplify supporting multiple
/// Bluetooth hosts from within a single HostDispatcher in the future.
pub struct GasProxy {
    service_request_stream: gatt::LocalServiceRequestStream,
    gas_task_channel: mpsc::Sender<gatt::LocalServiceRequest>,
    // We have to hold on to these connections to the Hosts GATT server even though we never use them because
    // otherwise the host will shut down the connection to the Generic Access Server.
    _gatt_server: gatt::Server_Proxy,
}

impl GasProxy {
    pub async fn new(
        gatt_server: gatt::Server_Proxy,
        gas_task_channel: mpsc::Sender<gatt::LocalServiceRequest>,
    ) -> Result<GasProxy, Error> {
        let (service_client, service_request_stream) =
            create_request_stream::<gatt::LocalServiceMarker>()?;
        let service_info = build_generic_access_service_info();
        gatt_server.publish_service(&service_info, service_client).await?.map_err(|e| {
            format_err!("Failed to publish Generic Access Service to GATT server: {:?}", e)
        })?;
        info!("Published Generic Access Service to local device database.");
        Ok(GasProxy { service_request_stream, gas_task_channel, _gatt_server: gatt_server })
    }

    pub async fn run(mut self) -> Result<(), Error> {
        while let Some(req) = self.service_request_stream.next().await {
            if let Err(send_err) = self.gas_task_channel.send(req?).await {
                if send_err.is_disconnected() {
                    return Ok(());
                }
                return Err(send_err.into());
            }
        }
        Ok(())
    }
}

/// Struct holding the state needed to run the Generic Access Service task, which
/// serves requests to the Generic Access Service from other devices per the BT spec.
/// To avoid shared state it reads back into HostDispatcher to see the values of the
/// service characteristics (name/appearance). The stream of requests is abstracted
/// from being tied to a specific host - HostDispatcher is set up so that when any
/// new host is set up, it ties the sender end of that channel to an instance of
/// the GAS Proxy task, which proxies the requests from that specific host to the
/// sender end of the channel stored in this struct.
pub struct GenericAccessService {
    hd: HostDispatcher,
    generic_access_req_stream: mpsc::Receiver<gatt::LocalServiceRequest>,
}

impl GenericAccessService {
    pub fn build(
        hd: &HostDispatcher,
        request_stream: mpsc::Receiver<gatt::LocalServiceRequest>,
    ) -> Self {
        Self { hd: hd.clone(), generic_access_req_stream: request_stream }
    }

    fn send_read_response(
        &self,
        responder: gatt::LocalServiceReadValueResponder,
        id: u64,
    ) -> Result<(), fidl::Error> {
        match id {
            GENERIC_ACCESS_DEVICE_NAME_ID => responder.send(Ok(self.hd.get_name().as_bytes())),
            GENERIC_ACCESS_APPEARANCE_ID => {
                responder.send(Ok(&self.hd.get_appearance().into_primitive().to_le_bytes()))
            }
            _ => responder.send(Err(gatt::Error::ReadNotPermitted)),
        }
    }

    fn process_service_req(&self, request: gatt::LocalServiceRequest) -> Result<(), Error> {
        match request {
            gatt::LocalServiceRequest::ReadValue { responder, handle, .. } => {
                Ok(self.send_read_response(responder, handle.value)?)
            }
            // Writing to the the available GENERIC_ACCESS service characteristics
            // is optional according to the spec, and it was decided not to implement
            gatt::LocalServiceRequest::WriteValue { responder, .. } => {
                Ok(responder.send(Err(gatt::Error::WriteNotPermitted))?)
            }
            gatt::LocalServiceRequest::PeerUpdate { payload: _, responder } => {
                Ok(responder.drop_without_shutdown())
            }
            // Ignore CharacteristicConfiguration, ValueChangedCredit, etc.
            _ => Ok(()),
        }
    }

    pub async fn run(mut self) {
        while let Some(request) = self.generic_access_req_stream.next().await {
            self.process_service_req(request).unwrap_or_else(|e| {
                warn!("Error handling Generic Access Service Request: {:?}", e);
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use async_helpers::hanging_get::asynchronous as hanging_get;
    use fidl::endpoints::create_proxy_and_stream;
    use fidl_fuchsia_bluetooth::{Appearance, PeerId};
    use fuchsia_async as fasync;
    use fuchsia_inspect as inspect;
    use futures::FutureExt;
    use std::collections::HashMap;

    use crate::host_dispatcher::{NameReplace, DEFAULT_DEVICE_NAME};
    use crate::store::stash::Stash;

    const TEST_DEVICE_APPEARANCE: Appearance = Appearance::Computer;

    // Starts tasks that run the GasProxy and GenericAccessService and returns the associated
    // LocalServiceProxy and HostDispatcher.
    fn setup_generic_access_service() -> (gatt::LocalServiceProxy, HostDispatcher) {
        let (service_client, service_request_stream) =
            create_proxy_and_stream::<gatt::LocalServiceMarker>().unwrap();
        let (gas_task_channel, generic_access_req_stream) =
            mpsc::channel::<gatt::LocalServiceRequest>(0);
        let (gatt_server, _gatt_server_remote) =
            create_proxy_and_stream::<gatt::Server_Marker>().unwrap();
        let gas_proxy = GasProxy {
            service_request_stream,
            gas_task_channel: gas_task_channel.clone(),
            _gatt_server: gatt_server,
        };
        fasync::Task::spawn(gas_proxy.run().map(|r| {
            r.unwrap_or_else(|err| {
                warn!("Error running Generic Access proxy in task: {:?}", err);
            })
        }))
        .detach();
        let stash = Stash::in_memory_mock();
        let inspector = inspect::Inspector::default();
        let system_inspect = inspector.root().create_child("system");
        let watch_peers_broker = hanging_get::HangingGetBroker::new(
            HashMap::new(),
            |_, _| true,
            hanging_get::DEFAULT_CHANNEL_SIZE,
        );
        let watch_hosts_broker = hanging_get::HangingGetBroker::new(
            Vec::new(),
            |_, _| true,
            hanging_get::DEFAULT_CHANNEL_SIZE,
        );
        let dispatcher = HostDispatcher::new(
            TEST_DEVICE_APPEARANCE,
            stash,
            system_inspect,
            gas_task_channel,
            watch_peers_broker.new_publisher(),
            watch_peers_broker.new_registrar(),
            watch_hosts_broker.new_publisher(),
            watch_hosts_broker.new_registrar(),
        );
        let service = GenericAccessService { hd: dispatcher.clone(), generic_access_req_stream };
        fasync::Task::spawn(service.run()).detach();
        (service_client, dispatcher)
    }

    #[fuchsia::test]
    async fn test_change_name() {
        let (delegate_client, host_dispatcher) = setup_generic_access_service();
        let expected_device_name = delegate_client
            .read_value(
                &PeerId { value: 1 },
                &gatt::Handle { value: GENERIC_ACCESS_DEVICE_NAME_ID },
                0,
            )
            .await
            .unwrap()
            .unwrap();
        assert_eq!(expected_device_name, DEFAULT_DEVICE_NAME.as_bytes());
        // This is expected to error since there is no host.
        let _ = host_dispatcher
            .set_name("test-generic-access-service-1".to_string(), NameReplace::Replace)
            .await
            .unwrap_err();
        let expected_device_name = delegate_client
            .read_value(
                &PeerId { value: 1 },
                &gatt::Handle { value: GENERIC_ACCESS_DEVICE_NAME_ID },
                0,
            )
            .await
            .unwrap()
            .unwrap();
        assert_eq!(expected_device_name, "test-generic-access-service-1".to_string().as_bytes());
    }

    #[fuchsia::test]
    async fn test_get_appearance() {
        let (service_client, _host_dispatcher) = setup_generic_access_service();
        let read_device_appearance = service_client
            .read_value(
                &PeerId { value: 1 },
                &gatt::Handle { value: GENERIC_ACCESS_APPEARANCE_ID },
                0,
            )
            .await
            .unwrap()
            .unwrap();
        assert_eq!(
            read_device_appearance,
            TEST_DEVICE_APPEARANCE.into_primitive().to_le_bytes().to_vec()
        );
    }

    #[fuchsia::test]
    async fn test_invalid_request() {
        let (service_client, _host_dispatcher) = setup_generic_access_service();
        let result = service_client
            .write_value(&gatt::LocalServiceWriteValueRequest {
                peer_id: Some(PeerId { value: 1 }),
                handle: Some(gatt::Handle { value: GENERIC_ACCESS_DEVICE_NAME_ID }),
                offset: Some(0),
                value: Some(b"new-name".to_vec()),
                ..Default::default()
            })
            .await
            .unwrap();
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), gatt::Error::WriteNotPermitted);
    }

    #[fuchsia::test]
    async fn test_gas_proxy() {
        let (service_client, service_request_stream) =
            create_proxy_and_stream::<gatt::LocalServiceMarker>().unwrap();
        let (gas_task_channel, mut generic_access_req_stream) =
            mpsc::channel::<gatt::LocalServiceRequest>(0);
        let (gatt_server, _gatt_server_remote) =
            create_proxy_and_stream::<gatt::Server_Marker>().unwrap();
        let gas_proxy =
            GasProxy { service_request_stream, gas_task_channel, _gatt_server: gatt_server };
        fasync::Task::spawn(gas_proxy.run().map(|r| {
            r.unwrap_or_else(|err| {
                warn!("Error running Generic Access proxy in task: {:?}", err);
            })
        }))
        .detach();
        let _ignored_fut = service_client.read_value(
            &PeerId { value: 1 },
            &gatt::Handle { value: GENERIC_ACCESS_APPEARANCE_ID },
            0,
        );
        let proxied_request = generic_access_req_stream.next().await.unwrap();
        let (_, handle, ..) = proxied_request.into_read_value().expect("ReadValue request");
        assert_eq!(handle.value, GENERIC_ACCESS_APPEARANCE_ID);
    }
}
