// Copyright 2020 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.

#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_TEST_SECURITY_MANAGER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_TEST_SECURITY_MANAGER_H_

#include <zircon/assert.h>

#include <memory>
#include <unordered_map>

#include "src/connectivity/bluetooth/core/bt-host/common/uint128.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/gap.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/link_key.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/security_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/status.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace bt::sm::testing {

// TestSecurityManager implements the public interface of the SM library. The intended use is in
// unit tests of code directly dependent on SM (currently, GAP). The implementation is currently
// limited to a basic test spy, with stubbed out responses and request tracking for a few functions
// and empty implementations for others.
class TestSecurityManager final : public SecurityManager {
 public:
  ~TestSecurityManager() = default;

  // SecurityManager overrides:
  bool AssignLongTermKey(const LTK& ltk) override;
  void UpgradeSecurity(SecurityLevel level, PairingCallback callback) override;
  void Reset(IOCapability io_capability) override;
  void Abort(ErrorCode ecode) override;

  // Returns the most recent security upgrade request received by this SM, if one has been made.
  std::optional<SecurityLevel> last_requested_upgrade() const { return last_requested_upgrade_; }

  fxl::WeakPtr<TestSecurityManager> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }

 private:
  friend class TestSecurityManagerFactory;
  TestSecurityManager(fxl::WeakPtr<hci::Connection> link, fbl::RefPtr<l2cap::Channel> smp,
                      IOCapability io_capability, fxl::WeakPtr<Delegate> delegate,
                      BondableMode bondable_mode, gap::LeSecurityMode security_mode);
  Role role_;
  std::optional<LTK> current_ltk_;
  std::optional<SecurityLevel> last_requested_upgrade_;
  fxl::WeakPtrFactory<TestSecurityManager> weak_ptr_factory_;
};

// TestSecurityManagerFactory provides a public factory method to create TestSecurityManagers for
// dependency injection. It stores these TestSMs so test code can access them to set and verify
// expectations. A separate storage object is needed because SecurityManagers cannot be directly
// injected, e.g. during construction, as they are created on demand upon connection creation.
// Storing the TestSMs in a factory object is preferable to a static member of TestSM itself so
// that each test is sandboxed from TestSMs in other tests. This is done by tying the lifetime of
// the factory to the test.
class TestSecurityManagerFactory {
 public:
  TestSecurityManagerFactory() = default;
  // Code which uses TestSecurityManagers should create these objects through `CreateSm`.
  // |link|: The LE logical link over which pairing procedures occur.
  // |smp|: The L2CAP LE SMP fixed channel that operates over |link|.
  // |io_capability|: The initial I/O capability.
  // |delegate|: Delegate which handles SMP interactions with the rest of the Bluetooth stack.
  // |bondable_mode|: the operating bondable mode of the device (see v5.2, Vol. 3, Part C 9.4).
  // |security_mode|: the security mode this SecurityManager is in (see v5.2, Vol. 3, Part C 10.2).
  std::unique_ptr<SecurityManager> CreateSm(fxl::WeakPtr<hci::Connection> link,
                                            fbl::RefPtr<l2cap::Channel> smp,
                                            IOCapability io_capability,
                                            fxl::WeakPtr<Delegate> delegate,
                                            BondableMode bondable_mode,
                                            gap::LeSecurityMode security_mode);

  // Obtain a reference to the TestSecurityManager associated with |conn_handle|'s connection for
  // use in test code.
  fxl::WeakPtr<testing::TestSecurityManager> GetTestSm(hci::ConnectionHandle conn_handle);

 private:
  std::unordered_map<hci::ConnectionHandle, fxl::WeakPtr<testing::TestSecurityManager>> test_sms_;
};

}  // namespace bt::sm::testing

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_TEST_SECURITY_MANAGER_H_
