// Copyright 2020 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 <algorithm>
#include <array>
#include <cstring>
#include <span>
#include <type_traits>

#include "pw_bytes/array.h"
#include "pw_bytes/bit.h"
#include "pw_bytes/span.h"

namespace pw::bytes {
namespace internal {

// Use a struct rather than an alias to give the type a more reasonable name.
template <typename T>
struct EquivalentUintImpl
    : std::conditional<
          sizeof(T) == 1,
          uint8_t,
          std::conditional_t<
              sizeof(T) == 2,
              uint16_t,
              std::conditional_t<
                  sizeof(T) == 4,
                  uint32_t,
                  std::conditional_t<sizeof(T) == 8, uint64_t, void>>>> {
  static_assert(std::is_integral_v<T>);
};

template <typename T>
using EquivalentUint = typename EquivalentUintImpl<T>::type;

template <typename T>
constexpr std::array<std::byte, sizeof(T)> CopyLittleEndian(T value) {
  return CopyLittleEndian(static_cast<EquivalentUint<T>>(value));
}

template <>
constexpr std::array<std::byte, 1> CopyLittleEndian<uint8_t>(uint8_t value) {
  return MakeArray(value);
}
template <>
constexpr std::array<std::byte, 2> CopyLittleEndian<uint16_t>(uint16_t value) {
  return MakeArray(value & 0x00FF, (value & 0xFF00) >> 8);
}

template <>
constexpr std::array<std::byte, 4> CopyLittleEndian<uint32_t>(uint32_t value) {
  return MakeArray((value & 0x000000FF) >> 0 * 8,
                   (value & 0x0000FF00) >> 1 * 8,
                   (value & 0x00FF0000) >> 2 * 8,
                   (value & 0xFF000000) >> 3 * 8);
}

template <>
constexpr std::array<std::byte, 8> CopyLittleEndian<uint64_t>(uint64_t value) {
  return MakeArray((value & 0x00000000000000FF) >> 0 * 8,
                   (value & 0x000000000000FF00) >> 1 * 8,
                   (value & 0x0000000000FF0000) >> 2 * 8,
                   (value & 0x00000000FF000000) >> 3 * 8,
                   (value & 0x000000FF00000000) >> 4 * 8,
                   (value & 0x0000FF0000000000) >> 5 * 8,
                   (value & 0x00FF000000000000) >> 6 * 8,
                   (value & 0xFF00000000000000) >> 7 * 8);
}

template <typename T>
constexpr T ReverseBytes(T value) {
  EquivalentUint<T> uint = static_cast<EquivalentUint<T>>(value);

  if constexpr (sizeof(uint) == 1) {
    return static_cast<T>(uint);
  } else if constexpr (sizeof(uint) == 2) {
    return static_cast<T>(((uint & 0x00FF) << 8) | ((uint & 0xFF00) >> 8));
  } else if constexpr (sizeof(uint) == 4) {
    return static_cast<T>(((uint & 0x000000FF) << 3 * 8) |  //
                          ((uint & 0x0000FF00) << 1 * 8) |  //
                          ((uint & 0x00FF0000) >> 1 * 8) |  //
                          ((uint & 0xFF000000) >> 3 * 8));
  } else {
    static_assert(sizeof(uint) == 8);
    return static_cast<T>(((uint & 0x00000000000000FF) << 7 * 8) |  //
                          ((uint & 0x000000000000FF00) << 5 * 8) |  //
                          ((uint & 0x0000000000FF0000) << 3 * 8) |  //
                          ((uint & 0x00000000FF000000) << 1 * 8) |  //
                          ((uint & 0x000000FF00000000) >> 1 * 8) |  //
                          ((uint & 0x0000FF0000000000) >> 3 * 8) |  //
                          ((uint & 0x00FF000000000000) >> 5 * 8) |  //
                          ((uint & 0xFF00000000000000) >> 7 * 8));
  }
}

}  // namespace internal

// Functions for reordering bytes in the provided integral value to match the
// specified byte order. These functions are similar to the htonl() family of
// functions.
//
// If the value is converted to non-system endianness, it must NOT be used
// directly, since the value will be meaningless. Such values are only suitable
// to memcpy'd or sent to a different device.
template <typename T>
constexpr T ConvertOrder(endian from, endian to, T value) {
  return from == to ? value : internal::ReverseBytes(value);
}

// Converts a value from native byte order to the specified byte order. Since
// this function changes the value's endianness, the result should only be used
// to memcpy the bytes to a buffer or send to a different device.
template <typename T>
constexpr T ConvertOrderTo(endian to_endianness, T value) {
  return ConvertOrder(endian::native, to_endianness, value);
}

// Converts a value from the specified byte order to the native byte order.
template <typename T>
constexpr T ConvertOrderFrom(endian from_endianness, T value) {
  return ConvertOrder(from_endianness, endian::native, value);
}

// Copies the value to a std::array with the specified endianness.
template <typename T>
constexpr auto CopyInOrder(endian order, T value) {
  return internal::CopyLittleEndian(ConvertOrderTo(order, value));
}

// Reads a value from a buffer with the specified endianness.
//
// The buffer **MUST** be at least sizeof(T) bytes large! If you are not
// absolutely certain the input buffer is large enough, use the ReadInOrder
// overload that returns bool, which checks the buffer size at runtime.
template <typename T>
T ReadInOrder(endian order, const void* buffer) {
  T value;
  std::memcpy(&value, buffer, sizeof(value));
  return ConvertOrderFrom(order, value);
}

// Reads up to the smaller of max_bytes_to_read and sizeof(T) bytes from a
// buffer with the specified endianness.
//
// The value is zero-initialized. If max_bytes_to_read is smaller than
// sizeof(T), the upper bytes of the value are 0.
//
// The buffer **MUST** be at least as large as the smaller of max_bytes_to_read
// and sizeof(T)!
template <typename T>
T ReadInOrder(endian order, const void* buffer, size_t max_bytes_to_read) {
  T value = {};
  std::memcpy(&value, buffer, std::min(sizeof(value), max_bytes_to_read));
  return ConvertOrderFrom(order, value);
}

// ReadInOrder from a static-extent span, with compile-time bounds checking.
template <typename T,
          typename B,
          size_t kBufferSize,
          typename = std::enable_if_t<kBufferSize != std::dynamic_extent &&
                                      sizeof(B) == sizeof(std::byte)>>
T ReadInOrder(endian order, std::span<B, kBufferSize> buffer) {
  static_assert(kBufferSize >= sizeof(T));
  return ReadInOrder<T>(order, buffer.data());
}

// ReadInOrder from a std::array, with compile-time bounds checking.
template <typename T, typename B, size_t kBufferSize>
T ReadInOrder(endian order, const std::array<B, kBufferSize>& buffer) {
  return ReadInOrder<T>(order, std::span(buffer));
}

// ReadInOrder from a C array, with compile-time bounds checking.
template <typename T, typename B, size_t kBufferSize>
T ReadInOrder(endian order, const B (&buffer)[kBufferSize]) {
  return ReadInOrder<T>(order, std::span(buffer));
}

// Reads a value with the specified endianness from the buffer, with bounds
// checking. Returns true if successful, false if buffer is too small for a T.
template <typename T>
[[nodiscard]] bool ReadInOrder(endian order, ConstByteSpan buffer, T& value) {
  if (buffer.size() < sizeof(T)) {
    return false;
  }

  value = ReadInOrder<T>(order, buffer.data());
  return true;
}

}  // namespace pw::bytes
