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

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())
        .IgnoreError();
    encoder.WriteSizeBytes(entry.SizeBytes()).IgnoreError();
    encoder.WritePermissions(entry.Permissions()).IgnoreError();
    encoder.WriteFileId(entry.FileId()).IgnoreError();
  }
  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(encoding_buffer_);
    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)
          .IgnoreError();  // TODO(pwbug/387): Handle Status properly
      return;
    }
  }
  writer.Finish(OkStatus())
      .IgnoreError();  // TODO(pwbug/387): Handle Status properly
}

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())
          .IgnoreError();  // TODO(pwbug/387): Handle Status properly
      return;
    }

    // Find and enumerate the file requested.
    Result<Entry*> result = FindFile(file_name_view);
    if (!result.ok()) {
      writer.Finish(result.status())
          .IgnoreError();  // TODO(pwbug/387): Handle Status properly
      return;
    }

    pw::file::ListResponse::MemoryEncoder encoder(encoding_buffer_);
    Status proto_encode_status = EnumerateFile(*result.value(), encoder);
    if (!proto_encode_status.ok()) {
      writer.Finish(proto_encode_status)
          .IgnoreError();  // TODO(pwbug/387): Handle Status properly
      return;
    }

    writer.Finish(writer.Write(encoder))
        .IgnoreError();  // TODO(pwbug/387): Handle Status properly
    return;
  }

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

void FlatFileSystemService::Delete(ConstByteSpan request,
                                   rpc::RawUnaryResponder& responder) {
  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()) {
      responder.Finish({}, Status::DataLoss()).IgnoreError();
      return;
    }
    responder.Finish({}, FindAndDeleteFile(file_name_view)).IgnoreError();
    return;
  }
  responder.Finish({}, Status::InvalidArgument()).IgnoreError();
}

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
