// 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 <climits>
#include <cstddef>
#include <cstdint>

namespace pw::kvs::internal {

// Tracks the available and used space in each sector used by the KVS.
class SectorDescriptor {
 public:
  explicit constexpr SectorDescriptor(uint16_t sector_size_bytes)
      : tail_free_bytes_(sector_size_bytes), valid_bytes_(0) {}

  SectorDescriptor(const SectorDescriptor&) = default;
  SectorDescriptor& operator=(const SectorDescriptor&) = default;

  // The number of bytes available to be written in this sector. It the sector
  // is marked as corrupt, no bytes are available.
  size_t writable_bytes() const {
    return (tail_free_bytes_ == kCorruptSector) ? 0 : tail_free_bytes_;
  }

  void set_writable_bytes(uint16_t writable_bytes) {
    tail_free_bytes_ = writable_bytes;
  }

  void mark_corrupt() { tail_free_bytes_ = kCorruptSector; }
  bool corrupt() const { return tail_free_bytes_ == kCorruptSector; }

  // The number of bytes of valid data in this sector.
  size_t valid_bytes() const { return valid_bytes_; }

  // Adds valid bytes without updating the writable bytes.
  void AddValidBytes(uint16_t bytes) { valid_bytes_ += bytes; }

  // Removes valid bytes without updating the writable bytes.
  void RemoveValidBytes(uint16_t bytes) {
    if (bytes > valid_bytes()) {
      // TODO: use a DCHECK instead -- this is a programming error
      valid_bytes_ = 0;
    } else {
      valid_bytes_ -= bytes;
    }
  }

  // Removes writable bytes without updating the valid bytes.
  void RemoveWritableBytes(uint16_t bytes) {
    if (bytes > writable_bytes()) {
      // TODO: use a DCHECK instead -- this is a programming error
      tail_free_bytes_ = 0;
    } else {
      tail_free_bytes_ -= bytes;
    }
  }

  bool HasSpace(size_t required_space) const {
    return writable_bytes() >= required_space;
  }

  bool Empty(size_t sector_size_bytes) const {
    return writable_bytes() == sector_size_bytes;
  }

  // Returns the number of bytes that would be recovered if this sector is
  // garbage collected.
  size_t RecoverableBytes(size_t sector_size_bytes) const {
    return sector_size_bytes - valid_bytes_ - writable_bytes();
  }

  static constexpr size_t max_sector_size() { return kMaxSectorSize; }

 private:
  static constexpr uint16_t kCorruptSector = UINT16_MAX;
  static constexpr size_t kMaxSectorSize = UINT16_MAX - 1;
  uint16_t tail_free_bytes_;  // writable bytes at the end of the sector
  uint16_t valid_bytes_;      // sum of sizes of valid entries
};

}  // namespace pw::kvs::internal
