// 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_file/flat_file_system.h"

#include <array>
#include <cstddef>
#include <cstdint>
#include <span>
#include <string_view>

#include "gtest/gtest.h"
#include "pw_bytes/span.h"
#include "pw_file/file.pwpb.h"
#include "pw_protobuf/decoder.h"
#include "pw_rpc/raw/test_method_context.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"

namespace pw::file {
namespace {

class FakeFile : public FlatFileSystemService::FileSystemEntry {
 public:
  constexpr FakeFile(std::string_view file_name, size_t size, uint32_t file_id)
      : name_(file_name), size_(size), file_id_(file_id) {}

  StatusWithSize Name(ByteSpan dest) override {
    if (name_.empty()) {
      return StatusWithSize(Status::NotFound(), 0);
    }

    size_t bytes_to_copy = std::min(dest.size_bytes(), name_.size());
    memcpy(dest.data(), name_.data(), bytes_to_copy);
    if (bytes_to_copy != name_.size()) {
      return StatusWithSize(Status::ResourceExhausted(), bytes_to_copy);
    }

    return StatusWithSize(OkStatus(), bytes_to_copy);
  }

  size_t SizeBytes() override { return size_; }

  FlatFileSystemService::FileSystemEntry::FilePermissions Permissions()
      override {
    return FlatFileSystemService::FileSystemEntry::FilePermissions::NONE;
  }

  Status Delete() override { return Status::Unimplemented(); }

  FlatFileSystemService::FileSystemEntry::Id FileId() override {
    return file_id_;
  }

 private:
  std::string_view name_;
  size_t size_;
  uint32_t file_id_;
};

bool FileSystemEntryHasName(FlatFileSystemService::FileSystemEntry* entry) {
  std::array<std::byte, 4> expected_name;
  StatusWithSize file_name_sws = entry->Name(expected_name);
  return file_name_sws.size() != 0;
}

// Compares a serialized Path message to a flat file system entry.
void ComparePathToEntry(ConstByteSpan serialized_path,
                        FlatFileSystemService::FileSystemEntry* entry) {
  std::array<std::byte, 64> expected_name;
  StatusWithSize file_name_sws = entry->Name(expected_name);

  // A partial name read shouldn't happen.
  ASSERT_EQ(OkStatus(), file_name_sws.status());

  protobuf::Decoder decoder(serialized_path);
  while (decoder.Next().ok()) {
    switch (decoder.FieldNumber()) {
      case static_cast<uint32_t>(pw::file::Path::Fields::PATH): {
        std::string_view serialized_name;
        EXPECT_EQ(OkStatus(), decoder.ReadString(&serialized_name));
        size_t name_bytes_to_read =
            std::min(serialized_name.size(), file_name_sws.size());
        EXPECT_EQ(0,
                  memcmp(expected_name.data(),
                         serialized_name.data(),
                         name_bytes_to_read));
        break;
      }

      case static_cast<uint32_t>(pw::file::Path::Fields::PERMISSIONS): {
        uint32_t seralized_permissions;
        EXPECT_EQ(OkStatus(), decoder.ReadUint32(&seralized_permissions));
        EXPECT_EQ(static_cast<uint32_t>(entry->Permissions()),
                  seralized_permissions);
        break;
      }

      case static_cast<uint32_t>(pw::file::Path::Fields::SIZE_BYTES): {
        uint32_t serialized_file_size;
        EXPECT_EQ(OkStatus(), decoder.ReadUint32(&serialized_file_size));
        EXPECT_EQ(static_cast<uint32_t>(entry->SizeBytes()),
                  serialized_file_size);
        break;
      }

      case static_cast<uint32_t>(pw::file::Path::Fields::FILE_ID): {
        uint32_t serialized_file_id;
        EXPECT_EQ(OkStatus(), decoder.ReadUint32(&serialized_file_id));
        EXPECT_EQ(static_cast<uint32_t>(entry->FileId()), serialized_file_id);
        break;
      }

      default:
        // unexpected result.
        // TODO something here.
        break;
    }
  }
}

size_t ValidateExpectedPaths(
    std::span<FlatFileSystemService::FileSystemEntry*> flat_file_system,
    const Vector<ByteSpan>& results) {
  size_t serialized_path_entry_count = 0;
  size_t file_system_index = 0;
  for (ConstByteSpan response : results) {
    protobuf::Decoder decoder(response);
    while (decoder.Next().ok()) {
      constexpr uint32_t kListResponsePathsFieldNumber =
          static_cast<uint32_t>(pw::file::ListResponse::Fields::PATHS);
      EXPECT_EQ(decoder.FieldNumber(), kListResponsePathsFieldNumber);
      if (decoder.FieldNumber() != kListResponsePathsFieldNumber) {
        return 0;
      }

      serialized_path_entry_count++;

      // Skip any file system entries without names.
      while (!FileSystemEntryHasName(flat_file_system[file_system_index])) {
        file_system_index++;
        EXPECT_GT(flat_file_system.size(), file_system_index);
      }

      // There's a 1:1 mapping in the same order for all files that have a name.
      ConstByteSpan serialized_path;
      EXPECT_EQ(OkStatus(), decoder.ReadBytes(&serialized_path));
      ComparePathToEntry(serialized_path,
                         flat_file_system[file_system_index++]);
    }
  }
  return serialized_path_entry_count;
}

TEST(FlatFileSystem, List_NoFiles) {
  std::array<std::byte, 1> file_name_buffer;

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemService, List)
  ctx(std::span<FlatFileSystemService::FileSystemEntry*>(), file_name_buffer);
  ctx.call(ConstByteSpan());

  EXPECT_TRUE(ctx.done());
  EXPECT_EQ(OkStatus(), ctx.status());
  EXPECT_EQ(0u, ctx.responses().size());
}

TEST(FlatFileSystem, List_OneFile) {
  std::array<std::byte, 20> file_name_buffer;
  FakeFile file{"compressed.zip.gz", 2, 1231};
  std::array<FlatFileSystemService::FileSystemEntry*, 1> static_file_system{
      &file};

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemService, List)
  ctx(static_file_system, file_name_buffer);
  ctx.call(ConstByteSpan());

  EXPECT_EQ(1u, ValidateExpectedPaths(static_file_system, ctx.responses()));
}

TEST(FlatFileSystem, List_ThreeFiles) {
  std::array<std::byte, 10> file_name_buffer;
  std::array<FakeFile, 3> files{
      {{"SNAP_001", 372, 9}, {"tokens.csv", 808, 15038202}, {"a.txt", 0, 2}}};
  std::array<FlatFileSystemService::FileSystemEntry*, 3> static_file_system{
      &files[0], &files[1], &files[2]};

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemService, List)
  ctx(static_file_system, file_name_buffer);
  ctx.call(ConstByteSpan());

  EXPECT_EQ(3u, ValidateExpectedPaths(static_file_system, ctx.responses()));
}

TEST(FlatFileSystem, List_UnnamedFile) {
  std::array<std::byte, 10> file_name_buffer;
  FakeFile file{"", 0, 0};
  std::array<FlatFileSystemService::FileSystemEntry*, 1> static_file_system{
      &file};

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemService, List)
  ctx(static_file_system, file_name_buffer);
  ctx.call(ConstByteSpan());

  EXPECT_EQ(0u, ValidateExpectedPaths(static_file_system, ctx.responses()));
}

TEST(FlatFileSystem, List_FileMissingName) {
  std::array<std::byte, 10> file_name_buffer;
  std::array<FakeFile, 3> files{
      {{"SNAP_001", 372, 9}, {"", 808, 15038202}, {"a.txt", 0, 2}}};
  std::array<FlatFileSystemService::FileSystemEntry*, 3> static_file_system{
      &files[0], &files[1], &files[2]};

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemService, List)
  ctx(static_file_system, file_name_buffer);
  ctx.call(ConstByteSpan());

  EXPECT_EQ(2u, ValidateExpectedPaths(static_file_system, ctx.responses()));
}

}  // namespace
}  // namespace pw::file
