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

#define PW_LOG_MODULE_NAME "FS"

#include "pw_file/flat_file_system.h"

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

#include "pw_assert/check.h"
#include "pw_bytes/span.h"
#include "pw_file/file.pwpb.h"
#include "pw_log/log.h"
#include "pw_protobuf/decoder.h"
#include "pw_protobuf/encoder.h"
#include "pw_protobuf/serialized_size.h"
#include "pw_rpc/raw/server_reader_writer.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"

namespace pw::file {

using Entry = FlatFileSystemService::Entry;

// TODO(pwbug/605): Remove this hack for accessing the PayloadBuffer() API.
class AccessHiddenFunctions : public rpc::RawServerWriter {
 public:
  using RawServerWriter::PayloadBuffer;
};

Status FlatFileSystemService::EnumerateFile(
    Entry& entry, pw::file::ListResponse::StreamEncoder& output_encoder) {
  StatusWithSize sws = entry.Name(file_name_buffer_);
  if (!sws.ok()) {
    return sws.status();
  }
  {
    pw::file::Path::StreamEncoder encoder = output_encoder.GetPathsEncoder();

    encoder.WritePath(reinterpret_cast<const char*>(file_name_buffer_.data()),
                      sws.size());
    encoder.WriteSizeBytes(entry.SizeBytes());
    encoder.WritePermissions(entry.Permissions());
    encoder.WriteFileId(entry.FileId());
  }
  return output_encoder.status();
}

void FlatFileSystemService::EnumerateAllFiles(RawServerWriter& writer) {
  for (Entry* entry : entries_) {
    PW_DCHECK_NOTNULL(entry);
    // For now, don't try to pack entries.
    pw::file::ListResponse::MemoryEncoder encoder(
        static_cast<AccessHiddenFunctions&>(writer).PayloadBuffer());
    if (Status status = EnumerateFile(*entry, encoder); !status.ok()) {
      if (status != Status::NotFound()) {
        PW_LOG_ERROR("Failed to enumerate file (id: %u) with status %d",
                     static_cast<unsigned>(entry->FileId()),
                     static_cast<int>(status.code()));
      }
      continue;
    }

    Status write_status = writer.Write(encoder);
    if (!write_status.ok()) {
      writer.Finish(write_status);
      return;
    }
  }
  writer.Finish(OkStatus());
}

void FlatFileSystemService::List(ConstByteSpan request,
                                 RawServerWriter& writer) {
  protobuf::Decoder decoder(request);
  // If a file name was provided, try and find and enumerate the file.
  while (decoder.Next().ok()) {
    if (decoder.FieldNumber() !=
        static_cast<uint32_t>(pw::file::ListRequest::Fields::PATH)) {
      continue;
    }

    std::string_view file_name_view;
    if (!decoder.ReadString(&file_name_view).ok() ||
        file_name_view.length() == 0) {
      writer.Finish(Status::DataLoss());
      return;
    }

    // Find and enumerate the file requested.
    Result<Entry*> result = FindFile(file_name_view);
    if (!result.ok()) {
      writer.Finish(result.status());
      return;
    }

    pw::file::ListResponse::MemoryEncoder encoder(
        static_cast<AccessHiddenFunctions&>(writer).PayloadBuffer());
    Status proto_encode_status = EnumerateFile(*result.value(), encoder);
    if (!proto_encode_status.ok()) {
      writer.Finish(proto_encode_status);
      return;
    }

    writer.Finish(writer.Write(encoder));
    return;
  }

  // If no path was provided in the ListRequest, just enumerate everything.
  EnumerateAllFiles(writer);
}

StatusWithSize FlatFileSystemService::Delete(ConstByteSpan request, ByteSpan) {
  protobuf::Decoder decoder(request);
  while (decoder.Next().ok()) {
    if (decoder.FieldNumber() !=
        static_cast<uint32_t>(pw::file::DeleteRequest::Fields::PATH)) {
      continue;
    }

    std::string_view file_name_view;
    if (!decoder.ReadString(&file_name_view).ok()) {
      return StatusWithSize(Status::DataLoss(), 0);
    }
    return StatusWithSize(FindAndDeleteFile(file_name_view), 0);
  }
  return StatusWithSize(Status::InvalidArgument(), 0);
}

Result<Entry*> FlatFileSystemService::FindFile(std::string_view file_name) {
  Status search_status;
  for (Entry* entry : entries_) {
    PW_DCHECK_NOTNULL(entry);
    StatusWithSize sws = entry->Name(file_name_buffer_);

    // If there not an exact file name length match, don't try and check against
    // a prefix.
    if (!sws.ok() || file_name.length() != sws.size()) {
      if (sws.status() != Status::NotFound()) {
        PW_LOG_ERROR("Failed to read file name (id: %u) with status %d",
                     static_cast<unsigned>(entry->FileId()),
                     static_cast<int>(sws.status().code()));
      }
      continue;
    }

    if (memcmp(file_name.data(), file_name_buffer_.data(), file_name.size()) ==
        0) {
      return entry;
    }
  }

  search_status.Update(Status::NotFound());
  return search_status;
}

Status FlatFileSystemService::FindAndDeleteFile(std::string_view file_name) {
  Result<Entry*> result = FindFile(file_name);
  if (!result.ok()) {
    return result.status();
  }

  return result.value()->Delete();
}

}  // namespace pw::file
