// 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_blob_store/flat_file_system_entry.h"

#include <array>
#include <cstddef>
#include <cstring>

#include "gtest/gtest.h"
#include "pw_blob_store/blob_store.h"
#include "pw_kvs/crc16_checksum.h"
#include "pw_kvs/fake_flash_memory.h"
#include "pw_kvs/flash_memory.h"
#include "pw_kvs/test_key_value_store.h"
#include "pw_random/xor_shift.h"
#include "pw_span/span.h"
#include "pw_sync/mutex.h"

namespace pw::blob_store {
namespace {

class FlatFileSystemBlobStoreEntryTest : public ::testing::Test {
 protected:
  static constexpr char kBlobTitle[] = "TestBlobBlock";
  static constexpr size_t kBufferSize = 64;

  FlatFileSystemBlobStoreEntryTest()
      : flash_(kFlashAlignment),
        partition_(&flash_),
        metadata_buffer_(),
        source_buffer_(),
        checksum_(),
        blob_(kBlobTitle, partition_, &checksum_, kvs::TestKvs(), kBufferSize) {
  }

  void SetUp() override { ASSERT_EQ(OkStatus(), blob_.Init()); }

  void InitSourceBufferToRandom(uint64_t seed,
                                size_t init_size_bytes = kBlobDataSize) {
    ASSERT_LE(init_size_bytes, source_buffer_.size());
    random::XorShiftStarRng64 rng(seed);

    std::memset(source_buffer_.data(),
                static_cast<int>(flash_.erased_memory_content()),
                source_buffer_.size());
    ASSERT_EQ(OkStatus(),
              rng.Get(span(source_buffer_).first(init_size_bytes)).status());
  }

  // Fill the source buffer with random pattern based on given seed, written to
  // BlobStore in specified chunk size.
  void WriteTestBlock(std::string_view file_name, size_t write_size_bytes) {
    ASSERT_LE(write_size_bytes, source_buffer_.size());

    ConstByteSpan write_data = span(source_buffer_).first(write_size_bytes);

    BlobStore::BlobWriter writer(blob_, metadata_buffer_);
    EXPECT_EQ(OkStatus(), writer.Open());
    ASSERT_EQ(OkStatus(), writer.SetFileName(file_name));
    ASSERT_EQ(OkStatus(), writer.Write(write_data));
    EXPECT_EQ(OkStatus(), writer.Close());

    // Use reader to check for valid data.
    BlobStore::BlobReader reader(blob_);
    ASSERT_EQ(OkStatus(), reader.Open());
    Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
    ASSERT_TRUE(result.ok());
    EXPECT_EQ(write_size_bytes, result.value().size_bytes());
    EXPECT_EQ(OkStatus(), reader.Close());
  }

  static constexpr size_t kFlashAlignment = 16;
  static constexpr size_t kSectorSize = 2048;
  static constexpr size_t kSectorCount = 2;
  static constexpr size_t kBlobDataSize = (kSectorCount * kSectorSize);
  static constexpr size_t kMaxFileNameLength = 32;
  static constexpr size_t kMetadataBufferSize =
      BlobStore::BlobWriter::RequiredMetadataBufferSize(kMaxFileNameLength);

  kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> flash_;
  kvs::FlashPartition partition_;
  std::array<std::byte, kMetadataBufferSize> metadata_buffer_;
  std::array<std::byte, kBlobDataSize> source_buffer_;
  kvs::ChecksumCrc16 checksum_;
  BlobStoreBuffer<kBufferSize> blob_;
};

TEST_F(FlatFileSystemBlobStoreEntryTest, BasicProperties) {
  constexpr size_t kWrittenDataSizeBytes = 104;
  constexpr uint32_t kExpectedFileId = 0x731ACAC0;
  constexpr FlatFileSystemBlobStoreEntry::FilePermissions kExpectedPermissions =
      FlatFileSystemBlobStoreEntry::FilePermissions::READ;

  constexpr std::string_view kFileName("my_file_1.bin");
  InitSourceBufferToRandom(0x5C4CA189);
  WriteTestBlock(kFileName, kWrittenDataSizeBytes);
  std::array<char, kMaxFileNameLength> tmp_buffer = {};
  static_assert(kFileName.size() <= tmp_buffer.size());

  sync::VirtualMutex blob_store_mutex;
  FlatFileSystemBlobStoreEntry blob_store_file(
      kExpectedFileId, kExpectedPermissions, blob_, blob_store_mutex);

  StatusWithSize sws = blob_store_file.Name(tmp_buffer);
  ASSERT_EQ(OkStatus(), sws.status());

  const int comparison =
      memcmp(tmp_buffer.data(), kFileName.data(), sws.size());
  EXPECT_EQ(0, comparison);
  EXPECT_EQ(kWrittenDataSizeBytes, blob_store_file.SizeBytes());
  EXPECT_EQ(kExpectedPermissions, blob_store_file.Permissions());
  EXPECT_EQ(kExpectedFileId, blob_store_file.FileId());
}

TEST_F(FlatFileSystemBlobStoreEntryTest, Delete) {
  constexpr size_t kWrittenDataSizeBytes = 104;
  constexpr uint32_t kExpectedFileId = 0x87ED0EF2;
  constexpr FlatFileSystemBlobStoreEntry::FilePermissions kExpectedPermissions =
      FlatFileSystemBlobStoreEntry::FilePermissions::READ;

  constexpr std::string_view kFileName("my_file_1.bin");
  InitSourceBufferToRandom(0x5C4CA189);
  WriteTestBlock(kFileName, kWrittenDataSizeBytes);

  sync::VirtualMutex blob_store_mutex;
  FlatFileSystemBlobStoreEntry blob_store_file(
      kExpectedFileId, kExpectedPermissions, blob_, blob_store_mutex);

  ASSERT_EQ(OkStatus(), blob_store_file.Delete());

  BlobStore::BlobReader reader(blob_);
  // Failed precondition is the expected return value when a BlobStore is opened
  // for reading and is empty.
  ASSERT_EQ(Status::FailedPrecondition(), reader.Open());
}

TEST_F(FlatFileSystemBlobStoreEntryTest, NoData) {
  constexpr uint32_t kExpectedFileId = 0x1;
  constexpr FlatFileSystemBlobStoreEntry::FilePermissions kExpectedPermissions =
      FlatFileSystemBlobStoreEntry::FilePermissions::READ;

  // Ensure the BlobStore is erased.
  ASSERT_EQ(OkStatus(), partition_.Erase());

  sync::VirtualMutex blob_store_mutex;
  FlatFileSystemBlobStoreEntry blob_store_file(
      kExpectedFileId, kExpectedPermissions, blob_, blob_store_mutex);

  std::array<char, kMaxFileNameLength> tmp_buffer = {};
  StatusWithSize sws = blob_store_file.Name(tmp_buffer);
  EXPECT_EQ(Status::NotFound(), sws.status());
  EXPECT_EQ(0u, sws.size());
}

}  // namespace
}  // namespace pw::blob_store
