// 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.
#pragma once

#include <memory>

#include "pw_bluetooth/gatt/constants.h"
#include "pw_bluetooth/gatt/error.h"
#include "pw_bluetooth/gatt/types.h"
#include "pw_bluetooth/result.h"
#include "pw_bluetooth/types.h"
#include "pw_containers/vector.h"
#include "pw_function/function.h"
#include "pw_result/result.h"
#include "pw_span/span.h"

namespace pw::bluetooth::gatt {

// Represents a GATT service on a remote GATT server.
// Clients should call `SetErrorCallback` before using in order to handle fatal
// errors.
class RemoteService {
 public:
  enum class RemoteServiceError {
    // The service has been modified or removed.
    kServiceRemoved = 0,

    // The peer serving this service has disconnected.
    kPeerDisconnected = 1,
  };

  // Wrapper around a possible truncated value received from the server.
  struct ReadValue {
    // Characteristic or descriptor handle.
    Handle handle;

    // The value of the characteristic or descriptor.
    Vector<std::byte> value;

    // True if `value` might be truncated (the buffer was completely filled by
    // the server and the read was a short read).  `ReadCharacteristic` or
    // `ReadDescriptor` should be used to read the complete value.
    bool maybe_truncated;
  };

  // A result returned by `ReadByType`.
  struct ReadByTypeResult {
    // Characteristic or descriptor handle.
    Handle handle;

    // The value of the characteristic or descriptor, if it was read
    // successfully, or an error explaining why the value could not be read.
    Result<Error, ReadValue> result;
  };

  // Represents the supported options to read a long characteristic or
  // descriptor value from a server. Long values are those that may not fit in a
  // single message (longer than 22 bytes).
  struct LongReadOptions {
    // The byte to start the read at. Must be less than the length of the
    // value.
    uint16_t offset = 0;

    // The maximum number of bytes to read.
    uint16_t max_bytes = kMaxValueLength;
  };

  // Represents the supported write modes for writing characteristics &
  // descriptors to the server.
  enum class WriteMode : uint8_t {
    // Wait for a response from the server before returning but do not verify
    // the echo response. Supported for both characteristics and descriptors.
    kDefault = 0,

    // Every value blob is verified against an echo response from the server.
    // The procedure is aborted if a value blob has not been reliably delivered
    // to the peer. Only supported for characteristics.
    kReliable = 1,

    // Delivery will not be confirmed before returning. Writing without a
    // response is only supported for short characteristics with the
    // `WRITE_WITHOUT_RESPONSE` property. The value must fit into a single
    // message. It is guaranteed that at least 20 bytes will fit into a single
    // message. If the value does not fit, a `kFailure` error will be produced.
    // The value will be written at offset 0. Only supported for
    // characteristics.
    kWithoutResponse = 2,
  };

  // Represents the supported options to write a characteristic/descriptor value
  // to a server.
  struct WriteOptions {
    // The mode of the write operation. For descriptors, only
    // `WriteMode::kDefault` is supported
    WriteMode mode = WriteMode::kDefault;

    // Request a write starting at the byte indicated.
    // Must be 0 if `mode` is `WriteMode.kWithoutResponse`.
    uint16_t offset = 0;
  };

  using ReadByTypeCallback = Function<void(Result<Vector<ReadByTypeResult>>)>;
  using ReadCallback = Function<void(Result<ReadValue>)>;
  using NotificationCallback = Function<void(ReadValue)>;

  // Set a callback that will be called when there is an error with this
  // RemoteService, after which this RemoteService will be invalid.
  void SetErrorCallback(Function<void(RemoteServiceError)> error_callback);

  // Calls `characteristic_callback` with the characteristics and descriptors in
  // this service.
  void DiscoverCharacteristics(
      Function<void(Characteristic)>&& characteristic_callback);

  // Reads characteristics and descriptors with the specified type. This method
  // is useful for reading values before discovery has completed, thereby
  // reducing latency.
  // `uuid` - The UUID of the characteristics/descriptors to read.
  // `result_callback` - Results are returned via this callback. Results may be
  //   empty if no matching values are read. If reading a value results in a
  //   permission error, the handle and error will be included.
  //
  // This may fail with the following errors:
  // kInvalidParameters: if `uuid` refers to an internally reserved descriptor
  //     type (e.g. the Client Characteristic Configuration descriptor).
  // kTooManyResults: More results were read than can fit
  //    in a Vector. Consider reading characteristics/descriptors individually
  //    after performing discovery.
  // kFailure: The server returned an error not specific to a single result.
  void ReadByType(Uuid uuid, ReadByTypeCallback&& result_callback);

  // Reads the value of a characteristic.
  // `handle` - The handle of the characteristic to be read.
  // `options` - If null, a short read will be performed, which may be truncated
  //     to what fits in a single message (at least 22 bytes). If long read
  //     options are present, performs a long read with the indicated options.
  // `result_callback` - called with the result of the read and the value of the
  //     characteristic if successful.
  //
  // This may fail with the following errors:
  // kInvalidHandle - if `handle` is invalid
  // kInvalidParameters - if `options is invalid
  // kReadNotPermitted or kInsufficient* if the server rejects the request.
  // kFailure if the server returns an error not covered by the above errors.
  void ReadCharacteristic(Handle handle,
                          std::optional<LongReadOptions> options,
                          ReadCallback&& result_callback);

  // Writes `value` to the characteristic with `handle` using the provided
  // `options`.  It is not recommended to send additional writes while a write
  // is already in progress (the server may receive simultaneous writes in any
  // order).
  //
  // Parameters:
  // `handle` - Handle of the characteristic to be written to
  // `value` - The value to be written.
  // `options` - Options that apply to the write.
  //
  // This may fail with the following errors:
  // kInvalidHandle - if `handle` is invalid
  // kInvalidParameters - if `options is invalid
  // kWriteNotPermitted or kInsufficient* if the server rejects the request.
  // kFailure if the server returns an error not covered by the above errors.
  void WriteCharacteristic(Handle handle,
                           span<const std::byte> value,
                           WriteOptions options,
                           Function<void(Result<Error>)>&& result_callback);

  // Reads the value of the characteristic descriptor with `handle` and
  // returns it in the reply.
  // `handle` - The descriptor handle to read.
  // `options` - Options that apply to the read.
  // `result_callback` - Returns a result containing the value of the descriptor
  //     on success.
  //
  // This may fail with the following errors:
  // `kInvalidHandle` - if `handle` is invalid.
  // `kInvalidParameters` - if `options` is invalid.
  // `kReadNotPermitted` or `INSUFFICIENT_*` - if the server rejects the read
  // request. `kFailure` - if the server returns an error.
  void ReadDescriptor(Handle handle,
                      std::optional<LongReadOptions> options,
                      ReadCallback&& result_callback);

  void WriteDescriptor(Handle handle,
                       span<const std::byte> value,
                       WriteOptions options,
                       Function<void(Result<Error>)>&& result_callback);

  // Subscribe to notifications & indications from the characteristic with
  // the given `handle`.
  //
  // Either notifications or indications will be enabled depending on
  // characteristic properties. Indications will be preferred if they are
  // supported. This operation fails if the characteristic does not have the
  // "notify" or "indicate" property.
  //
  // A write request will be issued to configure the characteristic for
  // notifications/indications if it contains a Client Characteristic
  // Configuration descriptor. This method fails if an error occurs while
  // writing to the descriptor.
  //
  // On success, `notification_callback` will be called when
  // the peer sends a notification or indication. Indications are
  // automatically confirmed.
  //
  // Subscriptions can be canceled with `StopNotifications`.
  //
  // Parameters:
  // `handle` - the handle of the characteristic to subscribe to.
  // `notification_callback` - will be called with the values of
  //     notifications/indications when received.
  // `result_callback` - called with the result of enabling
  //     notifications/indications.
  //
  // This may fail with the following errors:
  // `kFailure` - the characteristic does not support notifications or
  //     indications.
  // `kInvalidHandle` - `handle` is invalid.
  // `kWriteNotPermitted`or `kInsufficient*` - descriptor write error.
  void RegisterNotificationCallback(
      Handle handle,
      NotificationCallback&& notification_callback,
      Function<void(Result<Error>)> result_callback);

  // Stops notifications for the characteristic with the given `handle`.
  void StopNotifications(Handle handle);
};

// Represents a GATT client that interacts with services on a GATT server.
class Client {
 public:
  // Represents a remote GATT service.
  struct RemoteServiceInfo {
    // Uniquely identifies this GATT service.
    Handle handle;

    // Indicates whether this is a primary or secondary service.
    bool primary;

    // The UUID that identifies the type of this service.
    // There may be multiple services with the same UUID.
    Uuid type;
  };

  virtual ~Client() = default;

  // Enumerates existing services found on the peer that this Client represents,
  // and provides a stream of updates thereafter. Results can be filtered by
  // specifying a list of UUIDs in `uuids`. To further interact with services,
  // clients must obtain a RemoteService protocol by calling ConnectToService().
  // `uuid_allowlist` - The allowlist of UUIDs to filter services with.
  // `updated_callback` - Will be called with services that are
  //     updated/modified.
  // `removed_callback` - Called with the handles of servies
  //     that have been removed. Note that handles may be reused.
  virtual void WatchServices(
      Vector<Uuid> uuid_allowlist,
      Function<void(RemoteServiceInfo)>&& updated_callback,
      Function<void(Handle)>&& removed_callback) = 0;

  // Stops service watching if started by `WatchServices`.
  virtual void StopWatchingServices();

  // Connects to a RemoteService. Only 1 connection per service is allowed.
  // `handle` - the handle of the service to connect to.
  //
  // This may fail with the following errors:
  // kInvalidParameters - `handle` does not correspond to a known service.
  virtual Result<Error, std::unique_ptr<RemoteService>> ConnectToService(
      Handle handle) = 0;
};

}  // namespace pw::bluetooth::gatt
