// Copyright 2023 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 std::task::Poll;

use assert_matches::assert_matches;
use futures::{Future, FutureExt, StreamExt};

use bt_common::{PeerId, Uuid};

use crate::central::{AdvertisingDatum, PeerName, ScanResult};
use crate::server::{ServiceDefinition, ServiceEvent};
use crate::test_utils::*;
use crate::types::*;
use crate::{central::Filter, client::PeerService, server, Central};

const TEST_UUID_1: Uuid = Uuid::from_u16(0x1234);
const TEST_UUID_2: Uuid = Uuid::from_u16(0x2345);
const TEST_UUID_3: Uuid = Uuid::from_u16(0x3456);

// Sets up a fake peer service with some characteristics.
fn setup_peer_service() -> FakePeerService {
    let mut fake_peer_service = FakePeerService::new();
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(1),
            uuid: TEST_UUID_1,
            properties: CharacteristicProperties::BROADCAST_NOTIFY,
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![],
    );
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(2),
            uuid: TEST_UUID_1,
            properties: CharacteristicProperties::BROADCAST_NOTIFY,
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![],
    );
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(3),
            uuid: TEST_UUID_1,
            properties: CharacteristicProperties::BROADCAST_NOTIFY,
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![],
    );
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(4),
            uuid: TEST_UUID_2,
            properties: CharacteristicProperty::Notify.into(),
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![],
    );
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(5),
            uuid: TEST_UUID_3,
            properties: CharacteristicProperty::Broadcast.into(),
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![],
    );
    fake_peer_service
}

#[test]
fn peer_service_discover_characteristics_works() {
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

    let fake_peer_service = setup_peer_service();

    let mut discover_results = fake_peer_service.discover_characteristics(Some(TEST_UUID_1));
    let polled = discover_results.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok(chars)) => { assert_eq!(chars.len(), 3) });

    let mut discover_results = fake_peer_service.discover_characteristics(Some(TEST_UUID_2));
    let polled = discover_results.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok(chars)) => { assert_eq!(chars.len(), 1) });

    let mut discover_results =
        fake_peer_service.discover_characteristics(Some(Uuid::from_u16(0xFF22)));
    let polled = discover_results.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok(chars)) => { assert_eq!(chars.len(), 0) });

    let mut discover_results = fake_peer_service.discover_characteristics(None);
    let polled = discover_results.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok(chars)) => { assert_eq!(chars.len(), 5) });
}

#[test]
fn peer_service_read_characteristic() {
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

    let mut fake_peer_service = setup_peer_service();
    let mut buf = vec![0; 255];

    // For characteristic that was added, value is returned
    let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 0, &mut buf[..]);
    let polled: Poll<std::prelude::v1::Result<(usize, bool), Error>> =
        read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok((len, _))) => { assert_eq!(len, 0) });

    // For characteristic that doesn't exist, fails.
    let mut read_result = fake_peer_service.read_characteristic(&Handle(0xF), 0, &mut buf[..]);
    let polled = read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Err(_)));

    // Change the value for characteristic with handle 1.
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(1),
            uuid: TEST_UUID_1,
            properties: CharacteristicProperties::BROADCAST_NOTIFY,
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![0, 1, 2, 3],
    );

    // Successfully reads the updated value.
    let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 0, &mut buf[..]);
    let polled = read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => {
        assert_eq!(len, 4);
        assert_eq!(buf[..len], vec![0, 1, 2, 3]);
        assert!(!truncated);
    });

    // Read with small buffer (buf.len() < value.len()) sets truncated = true
    let mut small_buf = vec![0; 2];
    let mut read_result =
        fake_peer_service.read_characteristic(&Handle(0x1), 0, &mut small_buf[..]);
    let polled = read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => {
        assert_eq!(len, 2);
        assert_eq!(small_buf[..len], vec![0, 1]);
        assert!(truncated);
    });

    // Read with valid offset (offset = 2 < value.len())
    let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 2, &mut buf[..]);
    let polled = read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => {
        assert_eq!(len, 2);
        assert_eq!(buf[..len], vec![2, 3]);
        assert!(!truncated);
    });

    // Read with offset equal to value length (offset = 4 == value.len()) returns 0
    // bytes read
    let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 4, &mut buf[..]);
    let polled = read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Ok((len, truncated))) => {
        assert_eq!(len, 0);
        assert!(!truncated);
    });

    // Read with offset too large (offset = 5 > value.len()) returns
    // GattError::InvalidOffset
    let mut read_result = fake_peer_service.read_characteristic(&Handle(0x1), 5, &mut buf[..]);
    let polled = read_result.poll_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Err(Error::Gatt(GattError::InvalidOffset))));
}

#[test]
fn peer_service_write_characteristic() {
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

    let mut fake_peer_service: FakePeerService = setup_peer_service();

    // Set expected characteristic value before calling `write_characteristic`.
    fake_peer_service.expect_characteristic_value(&Handle(1), vec![0, 1, 2, 3]);
    let mut write_result = fake_peer_service.write_characteristic(
        &Handle(0x1),
        WriteMode::WithoutResponse,
        0,
        vec![0, 1, 2, 3].as_slice(),
    );

    match write_result.poll_unpin(&mut noop_cx) {
        Poll::Ready(Ok(())) => {}
        _ => panic!("expected write to succeed"),
    }
}

#[test]
#[should_panic]
fn peer_service_write_characteristic_fail() {
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

    let fake_peer_service = setup_peer_service();

    // Write some random value without calling `expect_characteristic_value` first.
    let mut write_result = fake_peer_service.write_characteristic(
        &Handle(0x1),
        WriteMode::WithoutResponse,
        0,
        vec![13, 14, 15, 16].as_slice(),
    );

    match write_result.poll_unpin(&mut noop_cx) {
        Poll::Ready(Err(_)) => {}
        _ => panic!("expected write to fail"),
    }
}

#[test]
fn peer_service_subscribe() {
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

    let mut fake_peer_service = setup_peer_service();
    let mut notification_stream = fake_peer_service.subscribe(&Handle(0x1));

    // Stream is empty unless we add an item through the FakeNotificationStream
    // struct.
    assert!(notification_stream.poll_next_unpin(&mut noop_cx).is_pending());

    // Update the characteristic value so that notification is sent.
    fake_peer_service.add_characteristic(
        Characteristic {
            handle: Handle(1),
            uuid: TEST_UUID_1,
            properties: CharacteristicProperties::BROADCAST_NOTIFY,
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        },
        vec![0, 1, 2, 3],
    );

    // Stream should be ready.
    let polled = notification_stream.poll_next_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Some(Ok(notification))) => {
        assert_eq!(notification.handle, Handle(0x1));
        assert_eq!(notification.value, vec![0,1,2,3]);
        assert_eq!(notification.maybe_truncated, false);
    });

    assert!(notification_stream.poll_next_unpin(&mut noop_cx).is_pending());
}

#[test]
fn central_search_works() {
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
    let central = FakeCentral::new();

    let mut scan_results = central.scan(&[Filter::ServiceUuid(Uuid::from_u16(0x1844)).into()]);
    let polled = scan_results.poll_next_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Pending);

    let scanned_result = ScanResult {
        id: PeerId(1),
        connectable: true,
        name: PeerName::CompleteName("Marie's Pixel 7 Pro".to_owned()),
        advertised: vec![AdvertisingDatum::Services(vec![Uuid::from_u16(0x1844)])],
        advertising_sid: Some(0),
        periodic_advertising_interval: None,
    };
    let controller = scan_results.controller();
    let _ = controller.add_scanned_result(Ok(scanned_result));

    let polled = scan_results.poll_next_unpin(&mut noop_cx);
    assert_matches!(polled, Poll::Ready(Some(Ok(_))));
}

fn boxed_generic_usage<T: crate::GattTypes>(central: Box<dyn crate::Central<T>>) {
    use crate::client::PeerServiceHandle;

    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
    let _stream = central.scan(&[]);

    let connect_fut = central.connect(PeerId(1));
    futures::pin_mut!(connect_fut);
    let Poll::Ready(Ok(client)) = connect_fut.poll(&mut noop_cx) else {
        panic!("Connect should be ready Ok");
    };

    let client_boxed: Box<dyn crate::client::Client<T>> = Box::new(client);

    let find_serv_fut = client_boxed.find_service(Uuid::from_u16(0));

    futures::pin_mut!(find_serv_fut);
    let Poll::Ready(Ok(services)) = find_serv_fut.poll(&mut noop_cx) else {
        panic!("Expected services future to resolve");
    };

    assert_eq!(services.len(), 1);

    let connect_service_fut = services[0].connect();

    futures::pin_mut!(connect_service_fut);
    let Poll::Ready(Ok(service)) = connect_service_fut.poll(&mut noop_cx) else {
        panic!("Expected service to connect");
    };

    let _service_box: Box<dyn crate::client::PeerService<T>> = Box::new(service);
}

#[test]
fn central_dynamic_usage() {
    let mut central = FakeCentral::new();
    let mut fake_client = FakeClient::new();
    fake_client.add_service(Uuid::from_u16(0), true, FakePeerService::new());
    central.add_client(PeerId(1), fake_client);

    let boxed: Box<dyn crate::Central<FakeTypes>> = Box::new(central);

    boxed_generic_usage(boxed);
}

/// Generate an example service definition with a variety of things in it.
fn example_service_definition() -> ServiceDefinition {
    let mut def =
        ServiceDefinition::new(server::ServiceId::new(1), TEST_UUID_1, ServiceKind::Primary);
    // Only readable
    def.add_characteristic(Characteristic {
        handle: Handle(1),
        uuid: TEST_UUID_2,
        properties: CharacteristicProperty::Read.into(),
        permissions: AttributePermissions {
            read: Some(SecurityLevels::default()),
            write: None,
            update: None,
        },
        descriptors: vec![],
    })
    .unwrap();
    // Only writable
    def.add_characteristic(Characteristic {
        handle: Handle(2),
        uuid: TEST_UUID_3,
        properties: CharacteristicProperty::Write.into(),
        permissions: AttributePermissions {
            read: None,
            write: Some(SecurityLevels::default()),
            update: None,
        },
        descriptors: vec![],
    })
    .unwrap();
    // Readable, writable, and notifiable
    def.add_characteristic(Characteristic {
        handle: Handle(3),
        uuid: TEST_UUID_3,
        properties: (&[
            CharacteristicProperty::Read,
            CharacteristicProperty::Write,
            CharacteristicProperty::Notify,
        ])
            .into(),
        permissions: AttributePermissions {
            read: Some(SecurityLevels::default()),
            write: Some(SecurityLevels::default()),
            update: Some(SecurityLevels::default()),
        },
        descriptors: vec![],
    })
    .unwrap();
    // Only Readable and Indicatable
    def.add_characteristic(Characteristic {
        handle: Handle(4),
        uuid: TEST_UUID_3,
        properties: (&[CharacteristicProperty::Read, CharacteristicProperty::Indicate]).into(),
        permissions: AttributePermissions {
            read: Some(SecurityLevels::default()),
            write: None,
            update: Some(SecurityLevels::default()),
        },
        descriptors: vec![],
    })
    .unwrap();
    def
}

#[test]
fn fake_server_usable() {
    use server::{LocalService, Server, ServiceId};
    let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

    let (server, mut events) = FakeServer::new();
    let mut local_service_fut = server.prepare(example_service_definition());

    let Poll::Ready(Ok(local_service)) = local_service_fut.poll_unpin(&mut noop_cx) else {
        panic!("Expected local service to prepare fine");
    };

    let mut service_event_stream = local_service.publish();

    // Published shouldn't be emitted until the service is present on the server.
    let Poll::Ready(Some(FakeServerEvent::Published { id, definition })) =
        events.poll_next_unpin(&mut noop_cx)
    else {
        panic!("Expected to generate an event from publishing");
    };

    assert_eq!(server::ServiceId::new(1), id);
    assert_eq!(definition.characteristics().count(), 4);

    server.incoming_read(PeerId(1), ServiceId::new(1), Handle(1), 0);

    let Poll::Ready(Some(Ok(ServiceEvent::Read { peer_id, handle, offset: _, responder }))) =
        service_event_stream.poll_next_unpin(&mut noop_cx)
    else {
        panic!("Expected read on the service stream");
    };

    assert_eq!(PeerId(1), peer_id);
    assert_eq!(Handle(1), handle);

    use server::ReadResponder;
    responder.respond(&[0, 1, 2, 3, 4, 5]);

    let Poll::Ready(Some(FakeServerEvent::ReadResponded { service_id, handle, value })) =
        events.poll_next_unpin(&mut noop_cx)
    else {
        panic!("Expected a read response");
    };

    assert_eq!(ServiceId::new(1), service_id);
    assert_eq!(Handle(1), handle);
    assert_eq!(&[0, 1, 2, 3, 4, 5], value.expect("should be ok").as_slice());
}
