// 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/common/device_address.h"

#include <map>
#include <unordered_map>

#include "pw_unit_test/framework.h"

namespace bt {
namespace {

// Initialize from bytes.
const DeviceAddress kClassic(DeviceAddress::Type::kBREDR,
                             {0x55, 0x44, 0x33, 0x22, 0x11, 0x41});
const DeviceAddress kPublic(DeviceAddress::Type::kLEPublic,
                            {0x42, 0x11, 0x22, 0x33, 0x44, 0x55});
const DeviceAddress kNonResolvable(DeviceAddress::Type::kLERandom,
                                   {0x55, 0x44, 0x33, 0x22, 0x11, 0x00});
const DeviceAddress kResolvable(DeviceAddress::Type::kLERandom,
                                {0x55, 0x44, 0x33, 0x22, 0x11, 0x43});
const DeviceAddress kStatic(DeviceAddress::Type::kLERandom,
                            {0x55, 0x44, 0x33, 0x22, 0x11, 0xC3});

struct TestPayload {
  uint8_t arg0;
  DeviceAddressBytes bdaddr;
} __attribute__((packed));

TEST(DeviceAddressBytesTest, ToString) {
  DeviceAddressBytes bdaddr({1, 15, 2, 255, 127, 3});
  EXPECT_EQ("03:7F:FF:02:0F:01", bdaddr.ToString());

  bdaddr = DeviceAddressBytes();
  EXPECT_EQ("00:00:00:00:00:00", bdaddr.ToString());
}

TEST(DeviceAddressBytesTest, CastFromBytes) {
  std::array<uint8_t, 7> bytes{{10, 1, 15, 2, 255, 127, 3}};
  EXPECT_EQ(bytes.size(), sizeof(TestPayload));

  auto* bdaddr = reinterpret_cast<DeviceAddressBytes*>(bytes.data());
  EXPECT_EQ("7F:FF:02:0F:01:0A", bdaddr->ToString());

  auto* test_payload = reinterpret_cast<TestPayload*>(bytes.data());
  EXPECT_EQ(10, test_payload->arg0);
  EXPECT_EQ("03:7F:FF:02:0F:01", test_payload->bdaddr.ToString());
}

TEST(DeviceAddressBytesTest, FromView) {
  std::array<uint8_t, 6> buffer = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xAA};
  auto bdaddr_view = pw::bluetooth::emboss::MakeBdAddrView(&buffer);
  DeviceAddressBytes addr(bdaddr_view);
  EXPECT_EQ("AA:FF:FF:FF:FF:FE", addr.ToString());
}

TEST(DeviceAddressBytesTest, ToView) {
  DeviceAddressBytes addr = DeviceAddressBytes({0, 0, 0, 0, 0, 0});
  EXPECT_EQ(addr.view().bd_addr().Read(), 0u);

  addr = DeviceAddressBytes({0xfe, 0xff, 0xff, 0xff, 0xff, 0xff});
  EXPECT_EQ(addr.view().bd_addr().Read(), 0xfffffffffffelu);
}

TEST(DeviceAddressBytesTest, Comparison) {
  DeviceAddressBytes bdaddr0, bdaddr1;
  EXPECT_EQ(bdaddr0, bdaddr1);

  bdaddr0 = DeviceAddressBytes({1, 2, 3, 4, 5, 6});
  EXPECT_NE(bdaddr0, bdaddr1);

  bdaddr1 = bdaddr0;
  EXPECT_EQ(bdaddr0, bdaddr1);
}

TEST(DeviceAddressTest, Comparison) {
  DeviceAddress addr0, addr1;
  EXPECT_EQ(addr0, addr1);

  addr0 = DeviceAddress(DeviceAddress::Type::kBREDR, {1, 2, 3, 4, 5, 6});
  EXPECT_NE(addr0, addr1);

  addr1 = DeviceAddress(DeviceAddress::Type::kLEPublic, addr0.value());
  EXPECT_EQ(addr0, addr1);

  addr0 = DeviceAddress(DeviceAddress::Type::kLERandom, addr0.value());
  EXPECT_NE(addr0, addr1);
}

TEST(DeviceAddressTest, Map) {
  std::map<DeviceAddress, int> map;

  DeviceAddress address1;
  DeviceAddress address2(address1);
  DeviceAddress address3(DeviceAddress::Type::kLEPublic, address1.value());
  DeviceAddress address4(DeviceAddress::Type::kLEPublic, {1});

  map[address1] = 1;

  auto iter = map.find(address1);
  EXPECT_NE(map.end(), iter);
  EXPECT_EQ(1, iter->second);

  iter = map.find(address2);
  EXPECT_NE(map.end(), iter);
  EXPECT_EQ(1, iter->second);

  iter = map.find(address3);
  EXPECT_NE(map.end(), iter);
  EXPECT_EQ(1, iter->second);

  iter = map.find(address4);
  EXPECT_EQ(map.end(), iter);

  map[address3] = 2;
  map[address4] = 3;

  EXPECT_EQ(2u, map.size());
  EXPECT_EQ(2, map[address1]);
  EXPECT_EQ(2, map[address2]);
  EXPECT_EQ(2, map[address3]);
  EXPECT_EQ(3, map[address4]);
}

TEST(DeviceAddressTest, UnorderedMap) {
  std::unordered_map<DeviceAddress, int> map;

  DeviceAddress address1;
  DeviceAddress address2(address1);
  DeviceAddress address3(DeviceAddress::Type::kLEPublic, address1.value());
  DeviceAddress address4(DeviceAddress::Type::kLEPublic, {1});

  map[address1] = 1;

  auto iter = map.find(address1);
  EXPECT_NE(map.end(), iter);
  EXPECT_EQ(1, iter->second);

  iter = map.find(address2);
  EXPECT_NE(map.end(), iter);
  EXPECT_EQ(1, iter->second);

  iter = map.find(address3);
  EXPECT_NE(map.end(), iter);
  EXPECT_EQ(1, iter->second);

  iter = map.find(address4);
  EXPECT_EQ(map.end(), iter);

  map[address3] = 2;
  map[address4] = 3;

  EXPECT_EQ(2u, map.size());
  EXPECT_EQ(2, map[address1]);
  EXPECT_EQ(2, map[address2]);
  EXPECT_EQ(2, map[address3]);
  EXPECT_EQ(3, map[address4]);
}

TEST(DeviceAddressTest, IsResolvablePrivate) {
  EXPECT_FALSE(kClassic.IsResolvablePrivate());
  EXPECT_FALSE(kPublic.IsResolvablePrivate());
  EXPECT_FALSE(kNonResolvable.IsResolvablePrivate());
  EXPECT_TRUE(kResolvable.IsResolvablePrivate());
  EXPECT_FALSE(kStatic.IsResolvablePrivate());
}

TEST(DeviceAddressTest, IsNonResolvablePrivate) {
  EXPECT_FALSE(kClassic.IsNonResolvablePrivate());
  EXPECT_FALSE(kPublic.IsNonResolvablePrivate());
  EXPECT_TRUE(kNonResolvable.IsNonResolvablePrivate());
  EXPECT_FALSE(kResolvable.IsNonResolvablePrivate());
  EXPECT_FALSE(kStatic.IsNonResolvablePrivate());
}

TEST(DeviceAddressTest, IsStatic) {
  EXPECT_FALSE(kClassic.IsStaticRandom());
  EXPECT_FALSE(kPublic.IsStaticRandom());
  EXPECT_FALSE(kNonResolvable.IsStaticRandom());
  EXPECT_FALSE(kResolvable.IsStaticRandom());
  EXPECT_TRUE(kStatic.IsStaticRandom());
}

TEST(DeviceAddressTest, IsPublic) {
  EXPECT_TRUE(kClassic.IsPublic());
  EXPECT_TRUE(kPublic.IsPublic());
  EXPECT_FALSE(kNonResolvable.IsPublic());
  EXPECT_FALSE(kResolvable.IsPublic());
  EXPECT_FALSE(kStatic.IsPublic());
}

}  // namespace
}  // namespace bt
