// Copyright 2022 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_profiles/device_info_service.h"

#include <string_view>

#include "gtest/gtest.h"
#include "pw_bluetooth/gatt/server.h"

using namespace std::string_view_literals;

namespace pw::bluetooth_profiles {
namespace {

class FakeGattServer final : public bluetooth::gatt::Server {
 public:
  // Server overrides:
  void PublishService(
      const bluetooth::gatt::LocalServiceInfo& info,
      bluetooth::gatt::LocalServiceDelegate* delegate,
      Function<void(PublishServiceResult)>&& result_callback) override {
    ASSERT_EQ(delegate_, nullptr);
    delegate_ = delegate;
    ASSERT_EQ(published_info_, nullptr);
    published_info_ = &info;
    local_service_.emplace(this);
    result_callback(
        PublishServiceResult(std::in_place, &local_service_.value()));
  }

  // PublishService call argument getters:
  const bluetooth::gatt::LocalServiceInfo* published_info() const {
    return published_info_;
  }
  bluetooth::gatt::LocalServiceDelegate* delegate() const { return delegate_; }

 private:
  class FakeLocalService final : public bluetooth::gatt::LocalService {
   public:
    explicit FakeLocalService(FakeGattServer* fake_server)
        : fake_server_(fake_server) {}

    // LocalService overrides:
    void NotifyValue(const ValueChangedParameters& /* parameters */,
                     Closure&& /* completion_callback */) override {
      FAIL();  // Unimplemented
    }
    void IndicateValue(
        const ValueChangedParameters& /* parameters */,
        Function<void(
            bluetooth::Result<bluetooth::gatt::Error>)>&& /* confirmation */)
        override {
      FAIL();  // Unimplemented
    }

   private:
    void UnpublishService() override { fake_server_->local_service_.reset(); }

    FakeGattServer* fake_server_;
  };

  // The LocalServiceInfo passed when PublishService was called.
  const bluetooth::gatt::LocalServiceInfo* published_info_ = nullptr;

  bluetooth::gatt::LocalServiceDelegate* delegate_ = nullptr;

  std::optional<FakeLocalService> local_service_;
};

TEST(DeviceInfoServiceTest, PublishAndReadTest) {
  FakeGattServer fake_server;

  constexpr auto kUsedFields = DeviceInfo::Field::kModelNumber |
                               DeviceInfo::Field::kSerialNumber |
                               DeviceInfo::Field::kSoftwareRevision;
  DeviceInfo device_info = {};
  const auto kModelNumber = "model"sv;
  device_info.model_number = as_bytes(span{kModelNumber});
  device_info.serial_number = as_bytes(span{"parallel_number"sv});
  device_info.software_revision = as_bytes(span{"rev123"sv});

  DeviceInfoService<kUsedFields, bluetooth::gatt::Handle{123}>
      device_info_service(device_info);

  bool called = false;
  device_info_service.PublishService(
      &fake_server,
      [&called](
          bluetooth::Result<bluetooth::gatt::Server::PublishServiceError> res) {
        EXPECT_TRUE(res.ok());
        called = true;
      });
  // The FakeGattServer calls the PublishService callback right away so our
  // callback should have been called already.
  EXPECT_TRUE(called);

  ASSERT_NE(fake_server.delegate(), nullptr);
  ASSERT_NE(fake_server.published_info(), nullptr);

  // Test that the published info looks correct.
  EXPECT_EQ(3u, fake_server.published_info()->characteristics.size());

  // Test that we can read the characteristics.
  for (auto& characteristic : fake_server.published_info()->characteristics) {
    bool read_callback_called = false;
    fake_server.delegate()->ReadValue(
        bluetooth::PeerId{1234},
        characteristic.handle,
        /*offset=*/0,
        [&read_callback_called](bluetooth::Result<bluetooth::gatt::Error,
                                                  span<const std::byte>> res) {
          EXPECT_TRUE(res.ok());
          EXPECT_NE(0u, res.value().size());
          read_callback_called = true;
        });
    // The DeviceInfoService always calls the callback from within ReadValue().
    EXPECT_TRUE(read_callback_called);
  }

  // Check the actual values.
  // The order of the characteristics in the LocalServiceInfo must be the order
  // in which the fields are listed in kCharacteristicFields, so the first
  // characteristic is the Model Number.
  span<const std::byte> read_value;
  fake_server.delegate()->ReadValue(
      bluetooth::PeerId{1234},
      fake_server.published_info()->characteristics[0].handle,
      /*offset=*/0,
      [&read_value](bluetooth::Result<bluetooth::gatt::Error,
                                      span<const std::byte>> res) {
        EXPECT_TRUE(res.ok());
        read_value = res.value();
      });
  EXPECT_EQ(read_value.size(), kModelNumber.size());  // "model" string.
  // DeviceInfoService keeps references to the values provides in the
  // DeviceInfo struct, not copies.
  EXPECT_EQ(read_value.data(),
            reinterpret_cast<const std::byte*>(kModelNumber.data()));

  // Read with an offset.
  const size_t kReadOffset = 3;
  fake_server.delegate()->ReadValue(
      bluetooth::PeerId{1234},
      fake_server.published_info()->characteristics[0].handle,
      kReadOffset,
      [&read_value](bluetooth::Result<bluetooth::gatt::Error,
                                      span<const std::byte>> res) {
        EXPECT_TRUE(res.ok());
        read_value = res.value();
      });
  EXPECT_EQ(read_value.size(), kModelNumber.size() - kReadOffset);
  EXPECT_EQ(
      read_value.data(),
      reinterpret_cast<const std::byte*>(kModelNumber.data()) + kReadOffset);
}

}  // namespace
}  // namespace pw::bluetooth_profiles
