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

#include "pw_kvs/internal/entry.h"

#include <cinttypes>
#include <cstring>

#include "pw_kvs_private/macros.h"
#include "pw_log/log.h"

namespace pw::kvs::internal {

using std::byte;
using std::string_view;

Status Entry::Read(FlashPartition& partition, Address address, Entry* entry) {
  EntryHeader header;
  TRY(partition.Read(address, sizeof(header), &header));

  if (partition.AppearsErased(as_bytes(span(&header.magic, 1)))) {
    return Status::NOT_FOUND;
  }
  if (header.key_length_bytes > kMaxKeyLength) {
    return Status::DATA_LOSS;
  }

  *entry = Entry(&partition, address, header);
  return Status::OK;
}

Status Entry::ReadKey(FlashPartition& partition,
                      Address address,
                      size_t key_length,
                      char* key) {
  if (key_length == 0u || key_length > kMaxKeyLength) {
    return Status::DATA_LOSS;
  }

  return partition.Read(address + sizeof(EntryHeader), key_length, key)
      .status();
}

Entry::Entry(FlashPartition& partition,
             Address address,
             const EntryFormat& format,
             string_view key,
             span<const byte> value,
             uint16_t value_size_bytes,
             size_t alignment_bytes,
             uint32_t transaction_id)
    : Entry(&partition,
            address,
            {.magic = format.magic,
             .checksum = 0,
             .alignment_units = alignment_bytes_to_units(alignment_bytes),
             .key_length_bytes = static_cast<uint8_t>(key.size()),
             .value_size_bytes = value_size_bytes,
             .transaction_id = transaction_id}) {
  if (format.checksum != nullptr) {
    span<const byte> checksum = CalculateChecksum(format.checksum, key, value);
    std::memcpy(&header_.checksum,
                checksum.data(),
                std::min(checksum.size(), sizeof(header_.checksum)));
  }

  // TODO: 0 is an invalid alignment value. There should be an assert for this.
  // DCHECK_NE(alignment_bytes, 0);
}

StatusWithSize Entry::Write(const string_view key,
                            span<const byte> value) const {
  FlashPartition::Output flash(partition(), address_);
  return AlignedWrite<64>(
      flash,
      alignment_bytes(),
      {as_bytes(span(&header_, 1)), as_bytes(span(key)), value});
}

StatusWithSize Entry::ReadValue(span<byte> buffer, size_t offset_bytes) const {
  if (offset_bytes > value_size()) {
    return StatusWithSize(Status::OUT_OF_RANGE);
  }

  const size_t remaining_bytes = value_size() - offset_bytes;
  const size_t read_size = std::min(buffer.size(), remaining_bytes);

  StatusWithSize result = partition().Read(
      address_ + sizeof(EntryHeader) + key_length() + offset_bytes,
      buffer.subspan(0, read_size));
  TRY_WITH_SIZE(result);

  if (read_size != remaining_bytes) {
    return StatusWithSize(Status::RESOURCE_EXHAUSTED, read_size);
  }
  return StatusWithSize(read_size);
}

Status Entry::VerifyChecksum(ChecksumAlgorithm* algorithm,
                             string_view key,
                             span<const byte> value) const {
  if (algorithm == nullptr) {
    return checksum() == 0 ? Status::OK : Status::DATA_LOSS;
  }
  CalculateChecksum(algorithm, key, value);
  return algorithm->Verify(checksum_bytes());
}

Status Entry::VerifyChecksumInFlash(ChecksumAlgorithm* algorithm) const {
  // Read the entire entry piece-by-piece into a small buffer. If the entry is
  // 32 B or less, only one read is required.
  union {
    EntryHeader header_to_verify;
    byte buffer[sizeof(EntryHeader) * 2];
  };

  size_t bytes_to_read = size();
  size_t read_size = std::min(sizeof(buffer), bytes_to_read);

  Address read_address = address_;

  // Read the first chunk, which includes the header, and compare the checksum.
  TRY(partition().Read(read_address, read_size, buffer));

  if (header_to_verify.checksum != checksum()) {
    PW_LOG_ERROR("Expected checksum %08" PRIx32 ", found %08" PRIx32,
                 checksum(),
                 header_to_verify.checksum);
    return Status::DATA_LOSS;
  }

  if (algorithm == nullptr) {
    return checksum() == 0 ? Status::OK : Status::DATA_LOSS;
  }

  // The checksum is calculated as if the header's checksum field were 0.
  header_to_verify.checksum = 0;

  algorithm->Reset();

  while (true) {
    // Add the chunk in the buffer to the checksum.
    algorithm->Update(buffer, read_size);

    bytes_to_read -= read_size;
    if (bytes_to_read == 0u) {
      break;
    }

    // Read the next chunk into the buffer.
    read_address += read_size;
    read_size = std::min(sizeof(buffer), bytes_to_read);
    TRY(partition().Read(read_address, read_size, buffer));
  }

  algorithm->Finish();
  return algorithm->Verify(checksum_bytes());
}

void Entry::DebugLog() {
  PW_LOG_DEBUG("Header: ");
  PW_LOG_DEBUG("   Address      = 0x%zx", size_t(address_));
  PW_LOG_DEBUG("   Magic        = 0x%zx", size_t(magic()));
  PW_LOG_DEBUG("   Checksum     = 0x%zx", size_t(checksum()));
  PW_LOG_DEBUG("   Key length   = 0x%zx", size_t(key_length()));
  PW_LOG_DEBUG("   Value length = 0x%zx", size_t(value_size()));
  PW_LOG_DEBUG("   Entry size   = 0x%zx", size_t(size()));
  PW_LOG_DEBUG("   Alignment    = 0x%zx", size_t(alignment_bytes()));
}

span<const byte> Entry::CalculateChecksum(ChecksumAlgorithm* algorithm,
                                          const string_view key,
                                          span<const byte> value) const {
  algorithm->Reset();

  {
    EntryHeader header_for_checksum = header_;
    header_for_checksum.checksum = 0;

    algorithm->Update(&header_for_checksum, sizeof(header_for_checksum));
    algorithm->Update(as_bytes(span(key)));
    algorithm->Update(value);
  }

  // Update the checksum with 0s to pad the entry to its alignment boundary.
  constexpr byte padding[kMinAlignmentBytes - 1] = {};
  size_t padding_to_add = Padding(content_size(), alignment_bytes());

  while (padding_to_add > 0u) {
    const size_t chunk_size = std::min(padding_to_add, sizeof(padding));
    algorithm->Update(padding, chunk_size);
    padding_to_add -= chunk_size;
  }

  return algorithm->Finish();
}

}  // namespace pw::kvs::internal
