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

#define PW_LOG_MODULE_NAME "KVS"
#define PW_LOG_LEVEL PW_KVS_LOG_LEVEL

#include "pw_kvs/internal/entry.h"

#include <cinttypes>
#include <cstring>

#include "pw_kvs_private/config.h"
#include "pw_log/log.h"
#include "pw_status/try.h"

namespace pw::kvs::internal {

static_assert(
    kMaxFlashAlignment >= Entry::kMinAlignmentBytes,
    "Flash alignment is required to be at least Entry::kMinAlignmentBytes");

constexpr size_t kWriteBufferSize =
    std::max(kMaxFlashAlignment, 4 * Entry::kMinAlignmentBytes);

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

Status Entry::Read(FlashPartition& partition,
                   Address address,
                   const internal::EntryFormats& formats,
                   Entry* entry) {
  EntryHeader header;
  PW_TRY(partition.Read(address, sizeof(header), &header));

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

  const EntryFormat* format = formats.Find(header.magic);
  if (format == nullptr) {
    PW_LOG_ERROR("Found corrupt magic: %" PRIx32 " at address %u",
                 header.magic,
                 unsigned(address));
    return Status::DataLoss();
  }

  *entry = Entry(&partition, address, *format, 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::DataLoss();
  }

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

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

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

Status Entry::Update(const EntryFormat& new_format,
                     uint32_t new_transaction_id) {
  checksum_algo_ = new_format.checksum;
  header_.magic = new_format.magic;
  header_.alignment_units =
      alignment_bytes_to_units(partition_->alignment_bytes());
  header_.transaction_id = new_transaction_id;

  // If we could write the header last, we could avoid reading the entry twice
  // when moving an entry. However, to support alignments greater than the
  // header size, we first read the entire value to calculate the new checksum,
  // then write the full entry in WriteFrom.
  return CalculateChecksumFromFlash();
}

StatusWithSize Entry::Copy(Address new_address) const {
  PW_LOG_DEBUG("Copying entry from %u to %u as ID %" PRIu32,
               unsigned(address()),
               unsigned(new_address),
               transaction_id());

  FlashPartition::Output output(partition(), new_address);
  AlignedWriterBuffer<kWriteBufferSize> writer(alignment_bytes(), output);

  // Use this object's header rather than the header in flash of flash, since
  // this Entry may have been updated.
  PW_TRY_WITH_SIZE(writer.Write(&header_, sizeof(header_)));

  // Write only the key and value from the original entry.
  FlashPartition::Input input(partition(), address() + sizeof(EntryHeader));
  PW_TRY_WITH_SIZE(writer.Write(input, key_length() + value_size()));
  return writer.Flush();
}

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

  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));
  PW_TRY_WITH_SIZE(result);

  if (read_size != remaining_bytes) {
    return StatusWithSize::ResourceExhausted(read_size);
  }
  return StatusWithSize(read_size);
}

Status Entry::ValueMatches(std::span<const std::byte> value) const {
  if (value_size() != value.size_bytes()) {
    return Status::NotFound();
  }

  Address address = address_ + sizeof(EntryHeader) + key_length();
  Address end = address + value_size();
  const std::byte* value_ptr = value.data();

  std::array<std::byte, 2 * kMinAlignmentBytes> buffer;
  while (address < end) {
    const size_t read_size = std::min(size_t(end - address), buffer.size());
    PW_TRY(partition_->Read(address, std::span(buffer).first(read_size)));

    if (std::memcmp(buffer.data(), value_ptr, read_size) != 0) {
      return Status::NotFound();
    }

    address += read_size;
    value_ptr += read_size;
  }

  return Status::Ok();
}

Status Entry::VerifyChecksum(string_view key,
                             std::span<const byte> value) const {
  if (checksum_algo_ == nullptr) {
    return header_.checksum == 0 ? Status::Ok() : Status::DataLoss();
  }
  CalculateChecksum(key, value);
  return checksum_algo_->Verify(checksum_bytes());
}

Status Entry::VerifyChecksumInFlash() 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.
  PW_TRY(partition().Read(read_address, read_size, buffer));

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

  if (checksum_algo_ == nullptr) {
    return header_.checksum == 0 ? Status::Ok() : Status::DataLoss();
  }

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

  checksum_algo_->Reset();

  while (true) {
    // Add the chunk in the buffer to the checksum.
    checksum_algo_->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);
    PW_TRY(partition().Read(read_address, read_size, buffer));
  }

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

void Entry::DebugLog() const {
  PW_LOG_DEBUG("Entry [%s]: ", deleted() ? "tombstone" : "present");
  PW_LOG_DEBUG("   Address      = 0x%x", unsigned(address_));
  PW_LOG_DEBUG("   Transaction  = %u", unsigned(transaction_id()));
  PW_LOG_DEBUG("   Magic        = 0x%x", unsigned(magic()));
  PW_LOG_DEBUG("   Checksum     = 0x%x", unsigned(header_.checksum));
  PW_LOG_DEBUG("   Key length   = 0x%x", unsigned(key_length()));
  PW_LOG_DEBUG("   Value length = 0x%x", unsigned(value_size()));
  PW_LOG_DEBUG("   Entry size   = 0x%x", unsigned(size()));
  PW_LOG_DEBUG("   Alignment    = 0x%x", unsigned(alignment_bytes()));
}

std::span<const byte> Entry::CalculateChecksum(
    const string_view key, std::span<const byte> value) const {
  checksum_algo_->Reset();

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

    checksum_algo_->Update(&header_for_checksum, sizeof(header_for_checksum));
    checksum_algo_->Update(std::as_bytes(std::span(key)));
    checksum_algo_->Update(value);
  }

  AddPaddingBytesToChecksum();

  return checksum_algo_->Finish();
}

Status Entry::CalculateChecksumFromFlash() {
  header_.checksum = 0;

  if (checksum_algo_ == nullptr) {
    return Status::Ok();
  }

  checksum_algo_->Reset();
  checksum_algo_->Update(&header_, sizeof(header_));

  Address address = address_ + sizeof(EntryHeader);
  // To handle alignment changes, do not read the padding. The padding is added
  // after checksumming the key and value from flash.
  const Address end = address_ + content_size();

  std::array<std::byte, 2 * kMinAlignmentBytes> buffer;
  while (address < end) {
    const size_t read_size = std::min(size_t(end - address), buffer.size());
    PW_TRY(partition_->Read(address, std::span(buffer).first(read_size)));

    checksum_algo_->Update(buffer.data(), read_size);
    address += read_size;
  }

  AddPaddingBytesToChecksum();

  std::span checksum = checksum_algo_->Finish();
  std::memcpy(&header_.checksum,
              checksum.data(),
              std::min(checksum.size(), sizeof(header_.checksum)));
  return Status::Ok();
}

void Entry::AddPaddingBytesToChecksum() const {
  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));
    checksum_algo_->Update(padding, chunk_size);
    padding_to_add -= chunk_size;
  }
}

}  // namespace pw::kvs::internal
