// 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());
}
