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

#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_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());
    rng.Get(std::span(source_buffer_).first(init_size_bytes))
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
  }

  // 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 =
        std::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.
  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
