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

#include "pw_transfer_private/chunk.h"

#include "pw_protobuf/decoder.h"
#include "pw_transfer/transfer.pwpb.h"

namespace pw::transfer::internal {

namespace ProtoChunk = transfer::Chunk;

Status DecodeChunk(ConstByteSpan message, Chunk& chunk) {
  protobuf::Decoder decoder(message);
  Status status;
  uint32_t value;

  chunk = {};

  while ((status = decoder.Next()).ok()) {
    ProtoChunk::Fields field =
        static_cast<ProtoChunk::Fields>(decoder.FieldNumber());

    switch (field) {
      case ProtoChunk::Fields::TRANSFER_ID:
        PW_TRY(decoder.ReadUint32(&chunk.transfer_id));
        break;

      case ProtoChunk::Fields::PENDING_BYTES:
        PW_TRY(decoder.ReadUint32(&value));
        chunk.pending_bytes = value;
        break;

      case ProtoChunk::Fields::MAX_CHUNK_SIZE_BYTES:
        PW_TRY(decoder.ReadUint32(&value));
        chunk.max_chunk_size_bytes = value;
        break;

      case ProtoChunk::Fields::MIN_DELAY_MICROSECONDS:
        PW_TRY(decoder.ReadUint32(&value));
        chunk.min_delay_microseconds = value;
        break;

      case ProtoChunk::Fields::OFFSET:
        PW_TRY(decoder.ReadUint32(&chunk.offset));
        break;

      case ProtoChunk::Fields::DATA:
        PW_TRY(decoder.ReadBytes(&chunk.data));
        break;

      case ProtoChunk::Fields::REMAINING_BYTES: {
        uint64_t remaining;
        PW_TRY(decoder.ReadUint64(&remaining));
        chunk.remaining_bytes = remaining;
        break;
      }

      case ProtoChunk::Fields::STATUS:
        PW_TRY(decoder.ReadUint32(&value));
        chunk.status = static_cast<Status::Code>(value);
        break;
    }
  }

  return status.IsOutOfRange() ? OkStatus() : status;
}

Result<ConstByteSpan> EncodeChunk(const Chunk& chunk, ByteSpan buffer) {
  ProtoChunk::MemoryEncoder encoder(buffer);

  encoder.WriteTransferId(chunk.transfer_id)
      .IgnoreError();  // TODO(pwbug/387): Handle Status properly

  if (chunk.pending_bytes.has_value()) {
    encoder.WritePendingBytes(chunk.pending_bytes.value())
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }
  if (chunk.max_chunk_size_bytes.has_value()) {
    encoder.WriteMaxChunkSizeBytes(chunk.max_chunk_size_bytes.value())
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }
  if (chunk.min_delay_microseconds.has_value()) {
    encoder.WriteMinDelayMicroseconds(chunk.min_delay_microseconds.value())
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }
  if (chunk.offset != 0) {
    encoder.WriteOffset(chunk.offset)
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }
  if (!chunk.data.empty()) {
    encoder.WriteData(chunk.data)
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }
  if (chunk.remaining_bytes.has_value()) {
    encoder.WriteRemainingBytes(chunk.remaining_bytes.value())
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }
  if (chunk.status.has_value()) {
    encoder.WriteStatus(chunk.status.value().code())
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }

  PW_TRY(encoder.status());
  return ConstByteSpan(encoder);
}

}  // namespace pw::transfer::internal
