// Copyright 2023 Google LLC
// 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::{FutureExt, StreamExt};

use bt_common::Uuid;

use crate::test_utils::*;
use crate::types::*;
use crate::{Central, central::Filter, client::PeerService};

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 set_up() -> FakePeerService {
    let mut fake_peer_service = FakePeerService::new();
    fake_peer_service.add_characteristic(Characteristic {
        handle: Handle(1),
        uuid: TEST_UUID_1,
        properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast, CharacteristicProperty::Notify]),
        permissions: AttributePermissions::default(),
        descriptors: vec![],
    }, vec![]);
    fake_peer_service.add_characteristic(Characteristic {
        handle: Handle(2),
        uuid: TEST_UUID_1,
        properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast, CharacteristicProperty::Notify]),
        permissions: AttributePermissions::default(),
        descriptors: vec![],
    }, vec![]);
    fake_peer_service.add_characteristic(Characteristic {
        handle: Handle(3),
        uuid: TEST_UUID_1,
        properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast, CharacteristicProperty::Notify]),
        permissions: AttributePermissions::default(),
        descriptors: vec![],
    }, vec![]);
    fake_peer_service.add_characteristic(Characteristic {
        handle: Handle(4),
        uuid: TEST_UUID_2,
        properties: CharacteristicProperties(vec![CharacteristicProperty::Notify]),
        permissions: AttributePermissions::default(),
        descriptors: vec![],
    }, vec![]);
    fake_peer_service.add_characteristic(Characteristic {
        handle: Handle(5),
        uuid: TEST_UUID_3,
        properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast]),
        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 = set_up();

    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 = set_up();
    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(vec![CharacteristicProperty::Broadcast, CharacteristicProperty::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, _))) => {
        assert_eq!(len, 4);
        assert_eq!(buf[..len], vec![0,1,2,3]);
    });
}

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

    let mut fake_peer_service = set_up();
    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(vec![CharacteristicProperty::Broadcast, CharacteristicProperty::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::default();

    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::Ready(Some(Ok(_))));
}
