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

#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_span/span.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"
#include "pw_unit_test/framework.h"

namespace pw::file {
namespace {

class FakeFile : public FlatFileSystemService::Entry {
 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(span<char> 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::Entry::FilePermissions Permissions() const override {
    return FlatFileSystemService::Entry::FilePermissions::NONE;
  }

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

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

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

bool EntryHasName(FlatFileSystemService::Entry* entry) {
  std::array<char, 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::Entry* entry) {
  std::array<char, 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::pwpb::Path::Fields::kPath): {
        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::pwpb::Path::Fields::kPermissions): {
        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::pwpb::Path::Fields::kSizeBytes): {
        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::pwpb::Path::Fields::kFileId): {
        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(amontanez) something here.
        break;
    }
  }
}

size_t ValidateExpectedPaths(
    span<FlatFileSystemService::Entry*> flat_file_system,
    const rpc::PayloadsView& 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::pwpb::ListResponse::Fields::kPaths);
      EXPECT_EQ(decoder.FieldNumber(), kListResponsePathsFieldNumber);
      if (decoder.FieldNumber() != kListResponsePathsFieldNumber) {
        return 0;
      }

      serialized_path_entry_count++;

      // Skip any file system entries without names.
      while (!EntryHasName(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, EncodingBufferSizeBytes) {
  EXPECT_EQ(FlatFileSystemService::EncodingBufferSizeBytes(10),
            2u /* path nested message key and size */ + 12 /* path */ +
                2 /* permissions */ + 6 /* size_bytes */ + 6 /* file_id */);
  EXPECT_EQ(FlatFileSystemService::EncodingBufferSizeBytes(10, 2),
            2 * (1u + 1 + 12 + 2 + 6 + 6));
  EXPECT_EQ(FlatFileSystemService::EncodingBufferSizeBytes(100, 3),
            3 * (1u + 1 + 102 + 2 + 6 + 6));
}

TEST(FlatFileSystem, List_NoFiles) {
  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemServiceWithBuffer<1>, List)
  ctx{span<FlatFileSystemService::Entry*>()};
  ctx.call(ConstByteSpan());

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

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

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemServiceWithBuffer<20>, List)
  ctx(static_file_system);
  ctx.call(ConstByteSpan());

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

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

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemServiceWithBuffer<10>, List)
  ctx(static_file_system);
  ctx.call(ConstByteSpan());

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

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

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemServiceWithBuffer<10>, List)
  ctx(static_file_system);
  ctx.call(ConstByteSpan());

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

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

  PW_RAW_TEST_METHOD_CONTEXT(FlatFileSystemServiceWithBuffer<10>, List)
  ctx(static_file_system);
  ctx.call(ConstByteSpan());

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

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