// 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 <algorithm>
#include <array>
#include <cstddef>
#include <cstring>

#include "pw_kvs/flash_memory.h"
#include "pw_span/span.h"
#include "pw_status/status.h"

namespace pw::kvs {

// This uses a buffer to mimic the behaviour of flash (requires erase before
// write, checks alignments, and is addressed in sectors). The underlying buffer
// is not initialized.
class InMemoryFakeFlash : public FlashMemory {
 public:
  // Default to 8-bit alignment.
  static constexpr size_t kDefaultAlignmentBytes = 1;

  static constexpr std::byte kErasedValue = std::byte{0xff};

  InMemoryFakeFlash(span<std::byte> buffer,
                    size_t sector_size,
                    size_t sector_count,
                    size_t alignment_bytes = kDefaultAlignmentBytes)
      : FlashMemory(sector_size, sector_count, alignment_bytes),
        buffer_(buffer) {}

  // The fake flash is always enabled.
  Status Enable() override { return Status::OK; }

  Status Disable() override { return Status::OK; }

  bool IsEnabled() const override { return true; }

  // Erase num_sectors starting at a given address.
  Status Erase(Address address, size_t num_sectors) override;

  // Reads bytes from flash into buffer.
  StatusWithSize Read(Address address, span<std::byte> output) override;

  // Writes bytes to flash.
  StatusWithSize Write(Address address, span<const std::byte> data) override;

  // Access the underlying buffer for testing purposes. Not part of the
  // FlashMemory API.
  span<std::byte> buffer() const { return buffer_; }

 private:
  const span<std::byte> buffer_;
};

// Creates an InMemoryFakeFlash backed by a std::array. The array is initialized
// to the erased value. A byte array to which to initialize the memory may be
// provided.
template <size_t kSectorSize, size_t kSectorCount>
class FakeFlashBuffer : public InMemoryFakeFlash {
 public:
  // Creates a flash memory with no data written.
  FakeFlashBuffer(size_t alignment_bytes = kDefaultAlignmentBytes)
      : FakeFlashBuffer(std::array<std::byte, 0>{}, alignment_bytes) {}

  // Creates a flash memory initialized to the provided contents.
  FakeFlashBuffer(span<const std::byte> contents,
                  size_t alignment_bytes = kDefaultAlignmentBytes)
      : InMemoryFakeFlash(buffer_, kSectorSize, kSectorCount, alignment_bytes) {
    std::memset(buffer_.data(), int(kErasedValue), buffer_.size());
    std::memcpy(buffer_.data(),
                contents.data(),
                std::min(contents.size(), buffer_.size()));
  }

 private:
  std::array<std::byte, kSectorCount * kSectorSize> buffer_;
};

}  // namespace pw::kvs
