// Copyright 2021 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 <bit>
#include <cstdint>
#include <optional>

#include "pw_assert/assert.h"
#include "pw_bytes/span.h"
#include "pw_result/result.h"

namespace pw::bluetooth_hci {

// HCI Packets as defined in the Bluetooth Core Specification Version 5.3
// “Host Controller Interface Functional Specification” in Volume 2, Part E.
//
// Note that for now only the subset of the HCI packets used in the HCI UART
// Transport Layer are provided as defined in the Bluetooth Core Specification
// version 5.3 "Host Controller Interface Transport Layer" volume 4, part A.
class CommandPacket;
class AsyncDataPacket;
class SyncDataPacket;
class EventPacket;

class Packet {
 public:
  enum class Type {
    kCommandPacket,
    kAsyncDataPacket,
    kSyncDataPacket,
    kEventPacket,
  };

  constexpr Type type() const { return type_; }

  constexpr size_t size_bytes() const { return packet_size_bytes_; }

  const CommandPacket& command_packet() const {
    PW_ASSERT(type_ == Type::kCommandPacket);
    return *reinterpret_cast<const CommandPacket*>(this);
  }

  CommandPacket& command_packet() {
    PW_ASSERT(type_ == Type::kCommandPacket);
    return *reinterpret_cast<CommandPacket*>(this);
  }

  const AsyncDataPacket& async_data_packet() const {
    PW_ASSERT(type_ == Type::kAsyncDataPacket);
    return *reinterpret_cast<const AsyncDataPacket*>(this);
  }

  AsyncDataPacket& async_data_packet() {
    PW_ASSERT(type_ == Type::kAsyncDataPacket);
    return *reinterpret_cast<AsyncDataPacket*>(this);
  }

  const SyncDataPacket& sync_data_packet() const {
    PW_ASSERT(type_ == Type::kSyncDataPacket);
    return *reinterpret_cast<const SyncDataPacket*>(this);
  }

  SyncDataPacket& sync_data_packet() {
    PW_ASSERT(type_ == Type::kSyncDataPacket);
    return *reinterpret_cast<SyncDataPacket*>(this);
  }

  const EventPacket& event_packet() const {
    PW_ASSERT(type_ == Type::kEventPacket);
    return *reinterpret_cast<const EventPacket*>(this);
  }

  EventPacket& event_packet() {
    PW_ASSERT(type_ == Type::kEventPacket);
    return *reinterpret_cast<EventPacket*>(this);
  }

 protected:
  constexpr Packet(Type type, size_t packet_size_bytes)
      : type_(type), packet_size_bytes_(packet_size_bytes) {}

 private:
  Type type_;
  size_t packet_size_bytes_;
};

class CommandPacket : public Packet {
 private:
  static constexpr size_t kOpcodeByteOffset = 0;
  static constexpr size_t kParameterTotalLengthByteOffset = 2;
  static constexpr size_t kParametersByteOffset = 3;

  static constexpr size_t kOpcodeOcfOffset = 0;
  static constexpr uint16_t kOpcodeOcfMask = 0x3FF << kOpcodeOcfOffset;
  static constexpr size_t kOpcodeOgfOffset = 10;
  static constexpr uint16_t kOpcodeOgfMask = 0x3F << kOpcodeOgfOffset;

 public:
  // HCI Command Packet Format, little-endian, based on bit offsets:
  // 0           16                        24            24+8*N
  // |  Opcode   |  Parameter Total Length | Parameter N |
  // 0     10    16
  // | OCF | OGF |
  static constexpr size_t kHeaderSizeBytes = kParametersByteOffset;

  constexpr CommandPacket(uint16_t opcode,
                          const std::byte* parameters,
                          uint8_t parameters_size_bytes)
      : Packet(Type::kCommandPacket, kHeaderSizeBytes + parameters_size_bytes),
        opcode_(opcode),
        parameters_(parameters, parameters_size_bytes) {}

  // Precondition: the parameters size must be <= 255 bytes.
  constexpr CommandPacket(uint16_t opcode, ConstByteSpan parameters)
      : CommandPacket(opcode,
                      parameters.data(),
                      static_cast<uint8_t>(parameters.size_bytes())) {
    PW_ASSERT(parameters.size_bytes() <= std::numeric_limits<uint8_t>::max());
  }

  // Decodes the packet based on the specified endianness.
  static std::optional<CommandPacket> Decode(
      ConstByteSpan data, std::endian order = std::endian::little);

  // Encodes the packet based on the specified endianness.
  //
  // Returns:
  //   OK - returns the encoded packet.
  //   RESOURCE_EXHAUSTED - The input buffer is too small for this packet.
  Result<ConstByteSpan> Encode(ByteSpan buffer,
                               std::endian order = std::endian::little) const;

  constexpr uint16_t opcode() const { return opcode_; }

  constexpr uint16_t opcode_command_field() const {
    return static_cast<uint16_t>((opcode_ & kOpcodeOcfMask) >>
                                 kOpcodeOcfOffset);
  }

  constexpr uint8_t opcode_group_field() const {
    return static_cast<uint8_t>((opcode_ & kOpcodeOgfMask) >> kOpcodeOgfOffset);
  }

  constexpr const ConstByteSpan& parameters() const { return parameters_; }

 private:
  uint16_t opcode_;
  ConstByteSpan parameters_;
};

class AsyncDataPacket : public Packet {
 private:
  static constexpr size_t kHandleAndFragmentationBitsByteOffset = 0;
  static constexpr size_t kDataTotalLengthByteOffset = 2;
  static constexpr size_t kDataByteOffset = 4;

  static constexpr size_t kHandleOffset = 0;
  static constexpr uint16_t kHandleMask = 0xFFF << kHandleOffset;
  static constexpr size_t kPbFlagOffset = 12;
  static constexpr uint16_t kPbFlagMask = 0x3 << kPbFlagOffset;
  static constexpr size_t kBcFlagOffset = 14;
  static constexpr uint16_t kBcFlagMask = 0x3 << kBcFlagOffset;

 public:
  // HCI ACL Data Packet Format, little-endian, based on bit offsets:
  // 0        12        14        16                  32       32+8*N
  // | Handle | PB Flag | BC Flag | Data Total Length | Data N |
  static constexpr size_t kHeaderSizeBytes = kDataByteOffset;

  constexpr AsyncDataPacket(uint16_t handle_and_fragmentation_bits,
                            const std::byte* data,
                            uint16_t data_size_bytes)
      : Packet(Type::kAsyncDataPacket, kHeaderSizeBytes + data_size_bytes),
        handle_and_fragmentation_bits_(handle_and_fragmentation_bits),
        data_(data, data_size_bytes) {}

  // Precondition: the parameters size must be <= 65535 bytes.
  constexpr AsyncDataPacket(uint16_t handle_and_fragmentation_bits,
                            ConstByteSpan data)
      : AsyncDataPacket(handle_and_fragmentation_bits,
                        data.data(),
                        static_cast<uint16_t>(data.size_bytes())) {
    PW_ASSERT(data.size_bytes() <= std::numeric_limits<uint16_t>::max());
  }

  // Decodes the packet based on the specified endianness.
  static std::optional<AsyncDataPacket> Decode(
      ConstByteSpan data, std::endian order = std::endian::little);

  // Encodes the packet based on the specified endianness.
  //
  // Returns:
  //   OK - returns the encoded packet.
  //   RESOURCE_EXHAUSTED - The input buffer is too small for this packet.
  Result<ConstByteSpan> Encode(ByteSpan buffer,
                               std::endian order = std::endian::little) const;

  constexpr uint16_t handle_and_fragmentation_bits() const {
    return handle_and_fragmentation_bits_;
  }

  constexpr uint16_t handle() const {
    return (handle_and_fragmentation_bits_ & kHandleMask) >> kHandleOffset;
  }

  constexpr uint8_t pb_flag() const {
    return static_cast<uint8_t>(
        (handle_and_fragmentation_bits_ & kPbFlagMask) >> kPbFlagOffset);
  }

  constexpr uint8_t bc_flag() const {
    return static_cast<uint8_t>(
        (handle_and_fragmentation_bits_ & kBcFlagMask) >> kBcFlagOffset);
  }

  constexpr const ConstByteSpan& data() const { return data_; }

 private:
  uint16_t handle_and_fragmentation_bits_;
  ConstByteSpan data_;
};

class SyncDataPacket : public Packet {
 private:
  static constexpr size_t kHandleAndStatusBitsByteOffset = 0;
  static constexpr size_t kDataTotalLengthByteOffset = 2;
  static constexpr size_t kDataByteOffset = 3;

  static constexpr size_t kHandleOffset = 0;
  static constexpr uint16_t kHandleMask = 0xFFF << kHandleOffset;
  static constexpr size_t kPacketStatusFlagOffset = 12;
  static constexpr uint16_t kPacketStatusFlagMask = 0x3
                                                    << kPacketStatusFlagOffset;

 public:
  // HCI SCO Data Packet Format, little-endian, based on bit offsets:
  // 0        12                   14         16                  24      24+8*N
  // | Handle | Packet Status Flag | Reserved | Data Total Length | Data N |
  static constexpr size_t kHeaderSizeBytes = 3;

  constexpr SyncDataPacket(uint16_t handle_and_status_bits,
                           const std::byte* data,
                           uint8_t data_size_bytes)
      : Packet(Type::kSyncDataPacket, kHeaderSizeBytes + data_size_bytes),
        handle_and_status_bits_(handle_and_status_bits),
        data_(data, data_size_bytes) {}

  // Precondition: the parameters size must be <= 255 bytes.
  constexpr SyncDataPacket(uint16_t handle_and_status_bits, ConstByteSpan data)
      : SyncDataPacket(handle_and_status_bits,
                       data.data(),
                       static_cast<uint8_t>(data.size_bytes())) {
    PW_ASSERT(data.size_bytes() <= std::numeric_limits<uint8_t>::max());
  }

  // Decodes the packet based on the specified endianness.
  static std::optional<SyncDataPacket> Decode(
      ConstByteSpan data, std::endian order = std::endian::little);

  // Encodes the packet based on the specified endianness.
  //
  // Returns:
  //   OK - returns the encoded packet.
  //   RESOURCE_EXHAUSTED - The input buffer is too small for this packet.
  Result<ConstByteSpan> Encode(ByteSpan buffer,
                               std::endian order = std::endian::little) const;

  constexpr uint16_t handle_and_status_bits() const {
    return handle_and_status_bits_;
  }

  constexpr uint16_t handle() const {
    return (handle_and_status_bits_ & kHandleMask) >> kHandleOffset;
  }

  constexpr uint8_t packet_status_flag() const {
    return static_cast<uint8_t>(
        (handle_and_status_bits_ & kPacketStatusFlagMask) >>
        kPacketStatusFlagOffset);
  }

  constexpr const ConstByteSpan& data() const { return data_; }

 private:
  uint16_t handle_and_status_bits_;
  ConstByteSpan data_;
};

class EventPacket : public Packet {
 private:
  static constexpr size_t kEventCodeByteOffset = 0;
  static constexpr size_t kParameterTotalLengthByteOffset = 1;
  static constexpr size_t kParametersByteOffset = 2;

 public:
  // HCI SCO Data Packet Format, little-endian, based on bit offsets:
  // 0            8                        16            16+8*N
  // | Event Code | Parameter Total Length | Parameter N |
  static constexpr size_t kHeaderSizeBytes = kParametersByteOffset;

  constexpr EventPacket(uint8_t event_code,
                        const std::byte* parameters,
                        uint8_t parameters_size_bytes)
      : Packet(Type::kEventPacket, kHeaderSizeBytes + parameters_size_bytes),
        event_code_(event_code),
        parameters_(parameters, parameters_size_bytes) {}

  // Precondition: the parameters size must be <= 255 bytes.
  constexpr EventPacket(uint16_t event_code, ConstByteSpan parameters)
      : EventPacket(event_code,
                    parameters.data(),
                    static_cast<uint8_t>(parameters.size_bytes())) {
    PW_ASSERT(parameters.size_bytes() <= std::numeric_limits<uint8_t>::max());
  }

  // Decodes the packet based on the specified endianness.
  static std::optional<EventPacket> Decode(ConstByteSpan data);

  // Encodes the packet based on the specified endianness.
  //
  // Returns:
  //   OK - returns the encoded packet.
  //   RESOURCE_EXHAUSTED - The input buffer is too small for this packet.
  Result<ConstByteSpan> Encode(ByteSpan buffer) const;

  constexpr uint8_t event_code() const { return event_code_; }

  constexpr const ConstByteSpan& parameters() const { return parameters_; }

 private:
  uint8_t event_code_;
  ConstByteSpan parameters_;
};

}  // namespace pw::bluetooth_hci
