// Copyright 2019 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 <cstddef>
#include <cstring>

#include "pw_protobuf/wire_format.h"
#include "pw_span/span.h"
#include "pw_status/status.h"
#include "pw_varint/varint.h"

namespace pw::protobuf {

// A streaming protobuf encoder which encodes to a user-specified buffer.
class Encoder {
 public:
  // TODO(frolv): Right now, only one intermediate size is supported. However,
  // this can be wasteful, as it requires 4 or 8 bytes of space per nested
  // message. This can be templated to minimize the overhead.
  using SizeType = size_t;

  constexpr Encoder(span<std::byte> buffer,
                    span<SizeType*> locations,
                    span<SizeType*> stack)
      : buffer_(buffer),
        cursor_(buffer.data()),
        blob_locations_(locations),
        blob_count_(0),
        blob_stack_(stack),
        depth_(0),
        encode_status_(Status::OK) {}

  // Disallow copy/assign to avoid confusion about who owns the buffer.
  Encoder(const Encoder& other) = delete;
  Encoder& operator=(const Encoder& other) = delete;

  // Per the protobuf specification, valid field numbers range between 1 and
  // 2**29 - 1, inclusive. The numbers 19000-19999 are reserved for internal
  // use.
  constexpr static uint32_t kMaxFieldNumber = (1u << 29) - 1;
  constexpr static uint32_t kFirstReservedNumber = 19000;
  constexpr static uint32_t kLastReservedNumber = 19999;

  // Writes a proto uint32 key-value pair.
  Status WriteUint32(uint32_t field_number, uint32_t value) {
    return WriteUint64(field_number, value);
  }

  // Writes a repeated uint32 using packed encoding.
  Status WritePackedUint32(uint32_t field_number, span<const uint32_t> values) {
    return WritePackedVarints(field_number, values, /*zigzag=*/false);
  }

  // Writes a proto uint64 key-value pair.
  Status WriteUint64(uint32_t field_number, uint64_t value);

  // Writes a repeated uint64 using packed encoding.
  Status WritePackedUint64(uint64_t field_number, span<const uint64_t> values) {
    return WritePackedVarints(field_number, values, /*zigzag=*/false);
  }

  // Writes a proto int32 key-value pair.
  Status WriteInt32(uint32_t field_number, int32_t value) {
    return WriteUint64(field_number, value);
  }

  // Writes a repeated int32 using packed encoding.
  Status WritePackedInt32(uint32_t field_number, span<const int32_t> values) {
    return WritePackedVarints(
        field_number,
        span(reinterpret_cast<const uint32_t*>(values.data()), values.size()),
        /*zigzag=*/false);
  }

  // Writes a proto int64 key-value pair.
  Status WriteInt64(uint32_t field_number, int64_t value) {
    return WriteUint64(field_number, value);
  }

  // Writes a repeated int64 using packed encoding.
  Status WritePackedInt64(uint32_t field_number, span<const int64_t> values) {
    return WritePackedVarints(
        field_number,
        span(reinterpret_cast<const uint64_t*>(values.data()), values.size()),
        /*zigzag=*/false);
  }

  // Writes a proto sint32 key-value pair.
  Status WriteSint32(uint32_t field_number, int32_t value) {
    return WriteUint64(field_number, varint::ZigZagEncode(value));
  }

  // Writes a repeated sint32 using packed encoding.
  Status WritePackedSint32(uint32_t field_number, span<const int32_t> values) {
    return WritePackedVarints(
        field_number,
        span(reinterpret_cast<const uint32_t*>(values.data()), values.size()),
        /*zigzag=*/true);
  }

  // Writes a proto sint64 key-value pair.
  Status WriteSint64(uint32_t field_number, int64_t value) {
    return WriteUint64(field_number, varint::ZigZagEncode(value));
  }

  // Writes a repeated sint64 using packed encoding.
  Status WritePackedSint64(uint32_t field_number, span<const int64_t> values) {
    return WritePackedVarints(
        field_number,
        span(reinterpret_cast<const uint64_t*>(values.data()), values.size()),
        /*zigzag=*/true);
  }

  // Writes a proto bool key-value pair.
  Status WriteBool(uint32_t field_number, bool value) {
    return WriteUint32(field_number, static_cast<uint32_t>(value));
  }

  // Writes a proto fixed32 key-value pair.
  Status WriteFixed32(uint32_t field_number, uint32_t value) {
    std::byte* original_cursor = cursor_;
    WriteFieldKey(field_number, WireType::kFixed32);
    Status status = WriteRawBytes(value);
    IncreaseParentSize(cursor_ - original_cursor);
    return status;
  }

  // Writes a repeated fixed32 field using packed encoding.
  Status WritePackedFixed32(uint32_t field_number,
                            span<const uint32_t> values) {
    return WriteBytes(field_number, as_bytes(values));
  }

  // Writes a proto fixed64 key-value pair.
  Status WriteFixed64(uint32_t field_number, uint64_t value) {
    std::byte* original_cursor = cursor_;
    WriteFieldKey(field_number, WireType::kFixed64);
    Status status = WriteRawBytes(value);
    IncreaseParentSize(cursor_ - original_cursor);
    return status;
  }

  // Writes a repeated fixed64 field using packed encoding.
  Status WritePackedFixed32(uint32_t field_number,
                            span<const uint64_t> values) {
    return WriteBytes(field_number, as_bytes(values));
  }

  // Writes a proto sfixed32 key-value pair.
  Status WriteSfixed32(uint32_t field_number, int32_t value) {
    return WriteFixed32(field_number, static_cast<uint32_t>(value));
  }

  // Writes a repeated sfixed32 field using packed encoding.
  Status WritePackedSfixed32(uint32_t field_number,
                             span<const int32_t> values) {
    return WriteBytes(field_number, as_bytes(values));
  }

  // Writes a proto sfixed64 key-value pair.
  Status WriteSfixed64(uint32_t field_number, int64_t value) {
    return WriteFixed64(field_number, static_cast<uint64_t>(value));
  }

  // Writes a repeated sfixed64 field using packed encoding.
  Status WritePackedSfixed64(uint32_t field_number,
                             span<const int64_t> values) {
    return WriteBytes(field_number, as_bytes(values));
  }

  // Writes a proto float key-value pair.
  Status WriteFloat(uint32_t field_number, float value) {
    static_assert(sizeof(float) == sizeof(uint32_t),
                  "Float and uint32_t are not the same size");
    std::byte* original_cursor = cursor_;
    WriteFieldKey(field_number, WireType::kFixed32);
    Status status = WriteRawBytes(value);
    IncreaseParentSize(cursor_ - original_cursor);
    return status;
  }

  // Writes a repeated float field using packed encoding.
  Status WritePackedFloat(uint32_t field_number, span<const float> values) {
    return WriteBytes(field_number, as_bytes(values));
  }

  // Writes a proto double key-value pair.
  Status WriteDouble(uint32_t field_number, double value) {
    static_assert(sizeof(double) == sizeof(uint64_t),
                  "Double and uint64_t are not the same size");
    std::byte* original_cursor = cursor_;
    WriteFieldKey(field_number, WireType::kFixed64);
    Status status = WriteRawBytes(value);
    IncreaseParentSize(cursor_ - original_cursor);
    return status;
  }

  // Writes a repeated double field using packed encoding.
  Status WritePackedDouble(uint32_t field_number, span<const double> values) {
    return WriteBytes(field_number, as_bytes(values));
  }

  // Writes a proto bytes key-value pair.
  Status WriteBytes(uint32_t field_number, span<const std::byte> value) {
    std::byte* original_cursor = cursor_;
    WriteFieldKey(field_number, WireType::kDelimited);
    WriteVarint(value.size_bytes());
    Status status = WriteRawBytes(value.data(), value.size_bytes());
    IncreaseParentSize(cursor_ - original_cursor);
    return status;
  }

  // Writes a proto string key-value pair.
  Status WriteString(uint32_t field_number, const char* value, size_t size) {
    return WriteBytes(field_number, as_bytes(span(value, size)));
  }

  Status WriteString(uint32_t field_number, const char* value) {
    return WriteString(field_number, value, strlen(value));
  }

  // Begins writing a sub-message with a specified field number.
  Status Push(uint32_t field_number);

  // Finishes writing a sub-message.
  Status Pop();

  // Returns the total encoded size of the proto message.
  size_t EncodedSize() const { return cursor_ - buffer_.data(); }

  // Returns the number of bytes remaining in the buffer.
  size_t RemainingSize() const { return buffer_.size() - EncodedSize(); }

  // Resets write index to the start of the buffer. This invalidates any spans
  // obtained from Encode().
  void Clear() {
    cursor_ = buffer_.data();
    encode_status_ = Status::OK;
    blob_count_ = 0;
    depth_ = 0;
  }

  // Runs a final encoding pass over the intermediary data and returns the
  // encoded protobuf message.
  Status Encode(span<const std::byte>* out);

 private:
  constexpr bool ValidFieldNumber(uint32_t field_number) const {
    return field_number != 0 && field_number <= kMaxFieldNumber &&
           !(field_number >= kFirstReservedNumber &&
             field_number <= kLastReservedNumber);
  }

  // Encodes the key for a proto field consisting of its number and wire type.
  Status WriteFieldKey(uint32_t field_number, WireType wire_type) {
    if (!ValidFieldNumber(field_number)) {
      encode_status_ = Status::INVALID_ARGUMENT;
      return encode_status_;
    }

    return WriteVarint(MakeKey(field_number, wire_type));
  }

  Status WriteVarint(uint64_t value);

  Status WriteZigzagVarint(int64_t value) {
    return WriteVarint(varint::ZigZagEncode(value));
  }

  template <typename T>
  Status WriteRawBytes(const T& value) {
    return WriteRawBytes(reinterpret_cast<const std::byte*>(&value),
                         sizeof(value));
  }

  Status WriteRawBytes(const std::byte* ptr, size_t size);

  // Writes a list of varints to the buffer in length-delimited packed encoding.
  // If zigzag is true, zig-zag encodes each of the varints.
  template <typename T>
  Status WritePackedVarints(uint32_t field_number,
                            span<T> values,
                            bool zigzag) {
    if (Status status = Push(field_number); !status.ok()) {
      return status;
    }

    std::byte* original_cursor = cursor_;
    for (T value : values) {
      if (zigzag) {
        WriteZigzagVarint(static_cast<std::make_signed_t<T>>(value));
      } else {
        WriteVarint(value);
      }
    }
    IncreaseParentSize(cursor_ - original_cursor);

    return Pop();
  }

  // Adds to the parent proto's size field in the buffer.
  void IncreaseParentSize(size_t bytes) {
    if (depth_ > 0) {
      *blob_stack_[depth_ - 1] += bytes;
    }
  }

  // Returns the size of `n` encoded as a varint.
  size_t VarintSizeBytes(uint64_t n) {
    size_t size_bytes = 1;
    while (n > 127) {
      ++size_bytes;
      n >>= 7;
    }
    return size_bytes;
  }

  // The buffer into which the proto is encoded.
  span<std::byte> buffer_;
  std::byte* cursor_;

  // List of pointers to sub-messages' delimiting size fields.
  span<SizeType*> blob_locations_;
  size_t blob_count_;

  // Stack of current nested message size locations. Push() operations add a new
  // entry to this stack and Pop() operations remove one.
  span<SizeType*> blob_stack_;
  size_t depth_;

  Status encode_status_;
};

// A proto encoder with its own blob stack.
template <size_t kMaxNestedDepth = 1, size_t kMaxBlobs = 1>
class NestedEncoder : public Encoder {
 public:
  NestedEncoder(span<std::byte> buffer) : Encoder(buffer, blobs_, stack_) {}

  // Disallow copy/assign to avoid confusion about who owns the buffer.
  NestedEncoder(const NestedEncoder& other) = delete;
  NestedEncoder& operator=(const NestedEncoder& other) = delete;

 private:
  std::array<size_t*, kMaxBlobs> blobs_;
  std::array<size_t*, kMaxNestedDepth> stack_;
};

// Explicit template argument deduction to hide warnings.
NestedEncoder()->NestedEncoder<>;

}  // namespace pw::protobuf
