// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_bluetooth_sapphire/internal/host/hci/android_extended_low_energy_advertiser.h"
#include "pw_bluetooth_sapphire/internal/host/hci/extended_low_energy_advertiser.h"
#include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
#include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h"

// Multiple advertising is supported by the Bluetooth 5.0+ Core Specification as
// well as Android vendor extensions. This test file contains shared tests for
// both versions of LE Multiple Advertising.

namespace bt::hci {
namespace {

using bt::testing::FakeController;
using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
using AdvertisingOptions = LowEnergyAdvertiser::AdvertisingOptions;
using LEAdvertisingState = FakeController::LEAdvertisingState;

constexpr AdvertisingIntervalRange kTestInterval(
    hci_spec::kLEAdvertisingIntervalMin, hci_spec::kLEAdvertisingIntervalMax);

const DeviceAddress kPublicAddress(DeviceAddress::Type::kLEPublic, {1});
const DeviceAddress kRandomAddress(DeviceAddress::Type::kLERandom, {2});

template <typename T>
class LowEnergyMultipleAdvertisingTest : public TestingBase {
 public:
  LowEnergyMultipleAdvertisingTest() = default;
  ~LowEnergyMultipleAdvertisingTest() override = default;

 protected:
  void SetUp() override {
    TestingBase::SetUp();

    // ACL data channel needs to be present for production hci::Connection
    // objects.
    TestingBase::InitializeACLDataChannel(
        hci::DataBufferInfo(),
        hci::DataBufferInfo(hci_spec::kMaxACLPayloadSize, 10));

    FakeController::Settings settings;
    settings.ApplyExtendedLEConfig();
    this->test_device()->set_settings(settings);

    advertiser_ = std::unique_ptr<T>(CreateAdvertiserInternal());
  }

  void TearDown() override {
    advertiser_ = nullptr;
    this->test_device()->Stop();
    TestingBase::TearDown();
  }

  template <bool same = std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>>
  std::enable_if_t<same, AndroidExtendedLowEnergyAdvertiser>*
  CreateAdvertiserInternal() {
    return new AndroidExtendedLowEnergyAdvertiser(transport()->GetWeakPtr(),
                                                  max_advertisements_);
  }

  template <bool same = std::is_same_v<T, ExtendedLowEnergyAdvertiser>>
  std::enable_if_t<same, ExtendedLowEnergyAdvertiser>*
  CreateAdvertiserInternal() {
    return new ExtendedLowEnergyAdvertiser(transport()->GetWeakPtr());
  }

  T* advertiser() const { return advertiser_.get(); }

  ResultFunction<> MakeExpectSuccessCallback() {
    return [this](Result<> status) {
      last_status_ = status;
      EXPECT_EQ(fit::ok(), status);
    };
  }

  ResultFunction<> MakeExpectErrorCallback() {
    return [this](Result<> status) {
      last_status_ = status;
      EXPECT_EQ(fit::failed(), status);
    };
  }

  static AdvertisingData GetExampleData(bool include_flags = true) {
    AdvertisingData result;

    std::string name = "fuchsia";
    EXPECT_TRUE(result.SetLocalName(name));

    uint16_t appearance = 0x1234;
    result.SetAppearance(appearance);

    EXPECT_LE(result.CalculateBlockSize(include_flags),
              hci_spec::kMaxLEAdvertisingDataLength);
    return result;
  }

  std::optional<Result<>> GetLastStatus() {
    if (!last_status_) {
      return std::nullopt;
    }

    return std::exchange(last_status_, std::nullopt).value();
  }

  uint8_t max_advertisements() const { return max_advertisements_; }

 private:
  std::unique_ptr<T> advertiser_;
  std::optional<Result<>> last_status_;
  uint8_t max_advertisements_ = 2;

  BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyMultipleAdvertisingTest);
};

using Implementations = ::testing::Types<ExtendedLowEnergyAdvertiser,
                                         AndroidExtendedLowEnergyAdvertiser>;
TYPED_TEST_SUITE(LowEnergyMultipleAdvertisingTest, Implementations);

TYPED_TEST(LowEnergyMultipleAdvertisingTest, LegacyPduLength) {
  EXPECT_EQ(hci_spec::kMaxLEAdvertisingDataLength,
            this->advertiser()->GetSizeLimit());
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest, AdvertisingHandlesExhausted) {
  this->test_device()->set_num_supported_advertising_sets(
      this->max_advertisements());

  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();
  AdvertisingOptions options(kTestInterval,
                             /*anonymous=*/false,
                             kDefaultNoAdvFlags,
                             /*include_tx_power_level=*/true);

  for (uint8_t i = 0; i < this->max_advertisements(); i++) {
    this->advertiser()->StartAdvertising(
        DeviceAddress(DeviceAddress::Type::kLEPublic, {i}),
        ad,
        scan_data,
        options,
        /*connect_callback=*/nullptr,
        this->MakeExpectSuccessCallback());
    this->RunUntilIdle();
  }

  ASSERT_TRUE(this->GetLastStatus());
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(this->max_advertisements(),
            this->advertiser()->NumAdvertisements());

  this->advertiser()->StartAdvertising(
      DeviceAddress(DeviceAddress::Type::kLEPublic,
                    {hci_spec::kAdvertisingHandleMax + 1}),
      ad,
      scan_data,
      options,
      /*connect_callback=*/nullptr,
      this->MakeExpectErrorCallback());

  this->RunUntilIdle();
  ASSERT_TRUE(this->GetLastStatus());
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(this->max_advertisements(),
            this->advertiser()->NumAdvertisements());
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest, SimultaneousAdvertisements) {
  this->test_device()->set_num_supported_advertising_sets(2);

  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();

  // start public address advertising
  AdvertisingOptions public_options(kTestInterval,
                                    /*anonymous=*/false,
                                    kDefaultNoAdvFlags,
                                    /*include_tx_power_level=*/false);
  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       public_options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->RunUntilIdle();
  std::optional<hci_spec::AdvertisingHandle> handle_public_addr =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle_public_addr);

  // start random address advertising
  constexpr AdvertisingIntervalRange random_interval(
      hci_spec::kLEAdvertisingIntervalMin + 1u,
      hci_spec::kLEAdvertisingIntervalMax - 1u);
  AdvertisingOptions random_options(random_interval,
                                    /*anonymous=*/false,
                                    kDefaultNoAdvFlags,
                                    /*include_tx_power_level=*/false);
  this->advertiser()->StartAdvertising(kRandomAddress,
                                       ad,
                                       scan_data,
                                       random_options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->RunUntilIdle();
  std::optional<hci_spec::AdvertisingHandle> handle_random_addr =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle_random_addr);

  // check everything is correct
  EXPECT_EQ(2u, this->advertiser()->NumAdvertisements());
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kRandomAddress));

  const LEAdvertisingState& public_addr_state =
      this->test_device()->extended_advertising_state(
          handle_public_addr.value());
  const LEAdvertisingState& random_addr_state =
      this->test_device()->extended_advertising_state(
          handle_random_addr.value());

  EXPECT_TRUE(public_addr_state.enabled);
  EXPECT_TRUE(random_addr_state.enabled);
  EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::PUBLIC,
            public_addr_state.own_address_type);
  EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::RANDOM,
            random_addr_state.own_address_type);
  EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMin,
            public_addr_state.interval_min);
  EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMax,
            public_addr_state.interval_max);
  EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMin + 1u,
            random_addr_state.interval_min);
  EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMax - 1u,
            random_addr_state.interval_max);
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest,
           StopAdvertisingAllAdvertisementsStopped) {
  this->test_device()->set_num_supported_advertising_sets(2);

  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();

  // start public address advertising
  AdvertisingOptions public_options(kTestInterval,
                                    /*anonymous=*/false,
                                    kDefaultNoAdvFlags,
                                    /*include_tx_power_level=*/false);
  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       public_options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->RunUntilIdle();
  std::optional<hci_spec::AdvertisingHandle> handle_public_addr =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle_public_addr);

  // start random address advertising
  constexpr AdvertisingIntervalRange random_interval(
      hci_spec::kLEAdvertisingIntervalMin + 1u,
      hci_spec::kLEAdvertisingIntervalMax - 1u);
  AdvertisingOptions random_options(random_interval,
                                    /*anonymous=*/false,
                                    kDefaultNoAdvFlags,
                                    /*include_tx_power_level=*/false);
  this->advertiser()->StartAdvertising(kRandomAddress,
                                       ad,
                                       scan_data,
                                       random_options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->RunUntilIdle();
  std::optional<hci_spec::AdvertisingHandle> handle_random_addr =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle_random_addr);

  // check everything is correct
  EXPECT_EQ(2u, this->advertiser()->NumAdvertisements());
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kRandomAddress));

  // Stop advertising
  this->advertiser()->StopAdvertising();
  this->RunUntilIdle();

  // Check that advertiser and controller both report not advertising
  EXPECT_EQ(0u, this->advertiser()->NumAdvertisements());
  EXPECT_FALSE(this->advertiser()->IsAdvertising());
  EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_FALSE(this->advertiser()->IsAdvertising(kRandomAddress));

  const LEAdvertisingState& public_addr_state =
      this->test_device()->extended_advertising_state(
          handle_public_addr.value());
  const LEAdvertisingState& random_addr_state =
      this->test_device()->extended_advertising_state(
          handle_random_addr.value());

  constexpr uint8_t blank[hci_spec::kMaxLEAdvertisingDataLength] = {0};

  EXPECT_FALSE(public_addr_state.enabled);
  EXPECT_EQ(0,
            std::memcmp(blank,
                        public_addr_state.data,
                        hci_spec::kMaxLEAdvertisingDataLength));
  EXPECT_EQ(0, public_addr_state.data_length);
  EXPECT_EQ(0,
            std::memcmp(blank,
                        public_addr_state.data,
                        hci_spec::kMaxLEAdvertisingDataLength));
  EXPECT_EQ(0, public_addr_state.scan_rsp_length);

  EXPECT_FALSE(random_addr_state.enabled);
  EXPECT_EQ(0,
            std::memcmp(blank,
                        random_addr_state.data,
                        hci_spec::kMaxLEAdvertisingDataLength));
  EXPECT_EQ(0, random_addr_state.data_length);
  EXPECT_EQ(0,
            std::memcmp(blank,
                        random_addr_state.data,
                        hci_spec::kMaxLEAdvertisingDataLength));
  EXPECT_EQ(0, random_addr_state.scan_rsp_length);
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest,
           StopAdvertisingSingleAdvertisement) {
  this->test_device()->set_num_supported_advertising_sets(2);

  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();

  // start public address advertising
  AdvertisingOptions public_options(kTestInterval,
                                    /*anonymous=*/false,
                                    kDefaultNoAdvFlags,
                                    /*include_tx_power_level=*/false);
  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       public_options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->RunUntilIdle();
  std::optional<hci_spec::AdvertisingHandle> handle_public_addr =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle_public_addr);

  // start random address advertising
  constexpr AdvertisingIntervalRange random_interval(
      hci_spec::kLEAdvertisingIntervalMin + 1u,
      hci_spec::kLEAdvertisingIntervalMax - 1u);
  AdvertisingOptions random_options(random_interval,
                                    /*anonymous=*/false,
                                    kDefaultNoAdvFlags,
                                    /*include_tx_power_level=*/false);
  this->advertiser()->StartAdvertising(kRandomAddress,
                                       ad,
                                       scan_data,
                                       random_options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->RunUntilIdle();
  std::optional<hci_spec::AdvertisingHandle> handle_random_addr =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle_random_addr);

  // check everything is correct
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(2u, this->advertiser()->NumAdvertisements());
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kRandomAddress));

  // Stop advertising the random address
  this->advertiser()->StopAdvertising(kRandomAddress);
  this->RunUntilIdle();

  // Check that advertiser and controller both report the same advertising state
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(1u, this->advertiser()->NumAdvertisements());
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_FALSE(this->advertiser()->IsAdvertising(kRandomAddress));

  constexpr uint8_t blank[hci_spec::kMaxLEAdvertisingDataLength] = {0};

  {
    const LEAdvertisingState& public_addr_state =
        this->test_device()->extended_advertising_state(
            handle_public_addr.value());
    const LEAdvertisingState& random_addr_state =
        this->test_device()->extended_advertising_state(
            handle_random_addr.value());

    EXPECT_TRUE(public_addr_state.enabled);
    EXPECT_NE(0,
              std::memcmp(blank,
                          public_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_NE(0, public_addr_state.data_length);
    EXPECT_NE(0,
              std::memcmp(blank,
                          public_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_NE(0, public_addr_state.scan_rsp_length);

    EXPECT_FALSE(random_addr_state.enabled);
    EXPECT_EQ(0,
              std::memcmp(blank,
                          random_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_EQ(0, random_addr_state.data_length);
    EXPECT_EQ(0,
              std::memcmp(blank,
                          random_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_EQ(0, random_addr_state.scan_rsp_length);
  }

  // stop advertising the public address
  this->advertiser()->StopAdvertising(kPublicAddress);
  this->RunUntilIdle();

  {
    const LEAdvertisingState& public_addr_state =
        this->test_device()->extended_advertising_state(
            handle_public_addr.value());
    const LEAdvertisingState& random_addr_state =
        this->test_device()->extended_advertising_state(
            handle_random_addr.value());

    // Check that advertiser and controller both report the same advertising
    // state
    EXPECT_FALSE(this->advertiser()->IsAdvertising());
    EXPECT_EQ(0u, this->advertiser()->NumAdvertisements());
    EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress));
    EXPECT_FALSE(this->advertiser()->IsAdvertising(kRandomAddress));

    EXPECT_FALSE(public_addr_state.enabled);
    EXPECT_EQ(0,
              std::memcmp(blank,
                          public_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_EQ(0, public_addr_state.data_length);
    EXPECT_EQ(0,
              std::memcmp(blank,
                          public_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_EQ(0, public_addr_state.scan_rsp_length);

    EXPECT_FALSE(random_addr_state.enabled);
    EXPECT_EQ(0,
              std::memcmp(blank,
                          random_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_EQ(0, random_addr_state.data_length);
    EXPECT_EQ(0,
              std::memcmp(blank,
                          random_addr_state.data,
                          hci_spec::kMaxLEAdvertisingDataLength));
    EXPECT_EQ(0, random_addr_state.scan_rsp_length);
  }
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest, SuccessiveAdvertisingCalls) {
  this->test_device()->set_num_supported_advertising_sets(2);

  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();
  AdvertisingOptions options(kTestInterval,
                             /*anonymous=*/false,
                             kDefaultNoAdvFlags,
                             /*include_tx_power_level=*/false);

  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->advertiser()->StartAdvertising(kRandomAddress,
                                       ad,
                                       scan_data,
                                       options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());

  this->RunUntilIdle();
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(2u, this->advertiser()->NumAdvertisements());
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kRandomAddress));

  this->advertiser()->StopAdvertising(kPublicAddress);
  this->advertiser()->StopAdvertising(kRandomAddress);

  this->RunUntilIdle();
  EXPECT_FALSE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(0u, this->advertiser()->NumAdvertisements());
  EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_FALSE(this->advertiser()->IsAdvertising(kRandomAddress));
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest, InterleavedAdvertisingCalls) {
  this->test_device()->set_num_supported_advertising_sets(
      this->max_advertisements());

  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();
  AdvertisingOptions options(kTestInterval,
                             /*anonymous=*/false,
                             kDefaultNoAdvFlags,
                             /*include_tx_power_level=*/false);

  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->advertiser()->StopAdvertising(kPublicAddress);
  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());

  this->RunUntilIdle();
  EXPECT_TRUE(this->advertiser()->IsAdvertising());
  EXPECT_EQ(1u, this->advertiser()->NumAdvertisements());
  EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
  EXPECT_FALSE(this->advertiser()->IsAdvertising(kRandomAddress));
}

TYPED_TEST(LowEnergyMultipleAdvertisingTest, StopWhileStarting) {
  AdvertisingData ad = this->GetExampleData();
  AdvertisingData scan_data = this->GetExampleData();
  AdvertisingOptions options(kTestInterval,
                             /*anonymous=*/false,
                             kDefaultNoAdvFlags,
                             /*include_tx_power_level=*/false);

  this->advertiser()->StartAdvertising(kPublicAddress,
                                       ad,
                                       scan_data,
                                       options,
                                       /*connect_callback=*/nullptr,
                                       this->MakeExpectSuccessCallback());
  this->advertiser()->StopAdvertising(kPublicAddress);

  this->RunUntilIdle();
  EXPECT_TRUE(this->GetLastStatus());

  std::optional<hci_spec::AdvertisingHandle> handle =
      this->advertiser()->LastUsedHandleForTesting();
  ASSERT_TRUE(handle);

  EXPECT_FALSE(
      this->test_device()->extended_advertising_state(handle.value()).enabled);
}

}  // namespace
}  // namespace bt::hci
