// 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::{format_err, Error},
    bt_test_harness::{
        access::{expectation, AccessHarness},
        deprecated::control::{activate_fake_host, ControlHarness},
        host_watcher::HostWatcherHarness,
    },
    fidl_fuchsia_bluetooth_sys::ProcedureTokenProxy,
    fidl_fuchsia_bluetooth_test::{AdvertisingData, LowEnergyPeerParameters, PeerProxy},
    fuchsia_bluetooth::{
        expectation::asynchronous::{ExpectableExt, ExpectableStateExt},
        hci_emulator::Emulator,
        types::{Address, HostId},
    },
    std::str::FromStr,
    test_harness::run_suite,
};

use crate::tests::timeout_duration;

async fn create_le_peer(hci: &Emulator, address: Address) -> Result<PeerProxy, Error> {
    let peer_params = LowEnergyPeerParameters {
        address: Some(address.into()),
        connectable: Some(true),
        advertisement: Some(AdvertisingData {
            data: vec![0x02, 0x01, 0x02], // Flags field set to "general discoverable"
        }),
        scan_response: None,
        ..LowEnergyPeerParameters::EMPTY
    };

    let (peer, remote) = fidl::endpoints::create_proxy()?;
    let _ = hci
        .emulator()
        .add_low_energy_peer(peer_params, remote)
        .await?
        .map_err(|e| format_err!("Failed to register fake peer: {:#?}", e))?;
    Ok(peer)
}

async fn start_discovery(access: &AccessHarness) -> Result<ProcedureTokenProxy, Error> {
    // We create a capability to capture the discovery token, and pass it to the access provider
    // Discovery will stop once we drop this token
    let (token, token_server) = fidl::endpoints::create_proxy()?;
    let fidl_response = access.aux().start_discovery(token_server);
    fidl_response
        .await?
        .map_err(|sys_err| format_err!("Error calling StartDiscovery(): {:?}", sys_err))?;
    Ok(token)
}

async fn make_discoverable(access: &AccessHarness) -> Result<ProcedureTokenProxy, Error> {
    // We create a capability to capture the discoverable token, and pass it to the access provider
    // Discoverable will stop once we drop this token
    let (token, token_server) = fidl::endpoints::create_proxy()?;
    let fidl_response = access.aux().make_discoverable(token_server);
    fidl_response
        .await?
        .map_err(|sys_err| format_err!("Error calling StartDiscoverable(): {:?}", sys_err))?;
    Ok(token)
}

// Test that we can
//  * Enable discovery via fuchsia.bluetooth.sys.Access.StartDiscovery()
//  * Receive peer information via fuchsia.bluetooth.sys.Access.WatchPeers()
async fn test_watch_peers((access, control): (AccessHarness, ControlHarness)) -> Result<(), Error> {
    let (_host, mut hci) = activate_fake_host(control, "bt-hci-integration").await?;

    let first_address = Address::Random([1, 0, 0, 0, 0, 0]);
    let second_address = Address::Public([2, 0, 0, 0, 0, 0]);
    let _first_peer = create_le_peer(&hci, first_address).await?;

    let _discovery_token = start_discovery(&access).await?;

    // We should be notified of the first peer
    let state = access
        .when_satisfied(expectation::peer_with_address(first_address), timeout_duration())
        .await?;

    // We should not have seen the second peer yet
    assert!(!expectation::peer_with_address(second_address).satisfied(&state));

    // Once the second peer is added, we should see it
    let _second_peer = create_le_peer(&hci, second_address).await?;
    let _state = access
        .when_satisfied(expectation::peer_with_address(second_address), timeout_duration())
        .await?;

    hci.destroy_and_wait().await?;
    Ok(())
}

async fn test_disconnect((access, control): (AccessHarness, ControlHarness)) -> Result<(), Error> {
    let (_host, mut hci) = activate_fake_host(control.clone(), "bt-hci-integration").await?;

    let peer_address = Address::Random([6, 5, 0, 0, 0, 0]);
    let _peer = create_le_peer(&hci, peer_address).await?;

    let _discovery = start_discovery(&access).await?;

    let state = access
        .when_satisfied(expectation::peer_with_address(peer_address), timeout_duration())
        .await?;

    // We can safely unwrap here as this is guarded by the previous expectation
    let peer_id = state.peers.values().find(|p| p.address == peer_address).unwrap().id;

    let fidl_response = access.aux().connect(&mut peer_id.into());
    fidl_response
        .await?
        .map_err(|sys_err| format_err!("Error calling Connect(): {:?}", sys_err))?;

    access.when_satisfied(expectation::peer_connected(peer_id, true), timeout_duration()).await?;

    let fidl_response = access.aux().disconnect(&mut peer_id.into());
    fidl_response
        .await?
        .map_err(|sys_err| format_err!("Error calling Disconnect(): {:?}", sys_err))?;

    access.when_satisfied(expectation::peer_connected(peer_id, false), timeout_duration()).await?;

    hci.destroy_and_wait().await?;
    Ok(())
}

// Test that we can
//  * Set local name via fuchsia.bluetooth.sys.Access.SetLocalName()
//  * Receive host information via fuchsia.bluetooth.sys.HostWatcher.Watch()
async fn test_set_local_name(
    (access, control, host_watcher): (AccessHarness, ControlHarness, HostWatcherHarness),
) -> Result<(), Error> {
    let (_host, mut hci) = activate_fake_host(control.clone(), "bt-hci-integration").await?;

    host_watcher.when_satisfied(expectation::host_with_name("fuchsia"), timeout_duration()).await?;

    let expected_name = "bt-integration-test";
    access.aux().set_local_name(expected_name)?;

    host_watcher
        .when_satisfied(expectation::host_with_name(expected_name), timeout_duration())
        .await?;

    hci.destroy_and_wait().await?;
    Ok(())
}

// Test that we can
//  * Enable discovery via fuchsia.bluetooth.sys.Access.StartDiscovery()
//  * Disable discovery by dropping our token
async fn test_discovery(
    (access, control, host_watcher): (AccessHarness, ControlHarness, HostWatcherHarness),
) -> Result<(), Error> {
    let (host, mut hci) = activate_fake_host(control.clone(), "bt-hci-integration").await?;
    let host = HostId::from_str(&host)?;
    let discovery_token = start_discovery(&access).await?;

    // We should now be discovering
    host_watcher
        .when_satisfied(expectation::host_discovering(host, true), timeout_duration())
        .await?;

    // Drop our end of the token channel
    std::mem::drop(discovery_token);

    // Since no-one else has requested discovery, we should cease discovery
    host_watcher
        .when_satisfied(expectation::host_discovering(host, false), timeout_duration())
        .await?;

    hci.destroy_and_wait().await?;
    Ok(())
}

// Test that we can
//  * Enable discoverable via fuchsia.bluetooth.sys.Access.StartDiscoverable()
//  * Disable discoverable by dropping our token
async fn test_discoverable(
    (access, control, host_watcher): (AccessHarness, ControlHarness, HostWatcherHarness),
) -> Result<(), Error> {
    let (host, mut hci) = activate_fake_host(control.clone(), "bt-hci-integration").await?;
    let host = HostId::from_str(&host)?;
    let discoverable_token = make_discoverable(&access).await?;

    // We should now be discoverable
    host_watcher
        .when_satisfied(expectation::host_discoverable(host, true), timeout_duration())
        .await?;

    // Drop our end of the token channel
    std::mem::drop(discoverable_token);

    // Since no-one else has requested discoverable, we should cease discoverable
    host_watcher
        .when_satisfied(expectation::host_discoverable(host, false), timeout_duration())
        .await?;

    hci.destroy_and_wait().await?;
    Ok(())
}

/// Run all test cases.
pub fn run_all() -> Result<(), Error> {
    run_suite!(
        "sys.Access",
        [test_watch_peers, test_disconnect, test_set_local_name, test_discoverable, test_discovery]
    )
}
