// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/fdio/vfs.h>
#include <lib/vfs/cpp/flags.h>
#include <lib/vfs/cpp/internal/file_connection.h>
#include <lib/vfs/cpp/pseudo_file.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <sstream>

namespace vfs {

PseudoFile::PseudoFile(size_t max_file_size, ReadHandler read_handler,
                       WriteHandler write_handler)
    : read_handler_(std::move(read_handler)),
      write_handler_(std::move(write_handler)),
      max_file_size_(max_file_size) {
  ZX_DEBUG_ASSERT(read_handler_ != nullptr);
}

PseudoFile::PseudoFile(DeprecatedReadHandler read_handler,
                       WriteHandler write_handler, size_t max_file_size)
    : PseudoFile(
          max_file_size,
          [read_handler = std::move(read_handler)](std::vector<uint8_t>* output,
                                                   size_t max_bytes) {
            return read_handler(output);
          },
          std::move(write_handler)) {}

PseudoFile::~PseudoFile() = default;

zx_status_t PseudoFile::CreateConnection(
    uint32_t flags, std::unique_ptr<vfs::internal::Connection>* connection) {
  std::vector<uint8_t> output;
  if (Flags::IsReadable(flags)) {
    zx_status_t status = read_handler_(&output, max_file_size_);
    if (status != ZX_OK) {
      return status;
    }
    if (output.size() > max_file_size_) {
      return ZX_ERR_FILE_BIG;
    }
  }
  *connection =
      std::make_unique<PseudoFile::Content>(this, flags, std::move(output));
  return ZX_OK;
}

zx_status_t PseudoFile::GetAttr(
    fuchsia::io::NodeAttributes* out_attributes) const {
  out_attributes->mode = fuchsia::io::MODE_TYPE_FILE;
  if (read_handler_ != nullptr)
    out_attributes->mode |= V_IRUSR;
  if (write_handler_)
    out_attributes->mode |= V_IWUSR;
  out_attributes->id = fuchsia::io::INO_UNKNOWN;
  out_attributes->content_size = 0;
  out_attributes->storage_size = 0;
  out_attributes->link_count = 1;
  out_attributes->creation_time = 0;
  out_attributes->modification_time = 0;
  return ZX_OK;
}

NodeKind::Type PseudoFile::GetKind() const {
  auto kind = File::GetKind() | NodeKind::kReadable;
  if (write_handler_ != nullptr) {
    kind |= NodeKind::kWritable | NodeKind::kCanTruncate;
  }
  return kind;
}

uint64_t PseudoFile::GetLength() {
  // this should never be called
  ZX_ASSERT(false);

  return 0u;
}

size_t PseudoFile::GetCapacity() {
  // this should never be called
  ZX_DEBUG_ASSERT(false);

  return max_file_size_;
}

PseudoFile::Content::Content(PseudoFile* file, uint32_t flags,
                             std::vector<uint8_t> content)
    : Connection(flags),
      file_(file),
      buffer_(std::move(content)),
      flags_(flags) {
  SetInputLength(buffer_.size());
}

PseudoFile::Content::~Content() { TryFlushIfRequired(); }

zx_status_t PseudoFile::Content::TryFlushIfRequired() {
  if (!dirty_) {
    return ZX_OK;
  }
  dirty_ = false;
  return file_->write_handler_(std::move(buffer_));
}

zx_status_t PseudoFile::Content::PreClose(Connection* connection) {
  return TryFlushIfRequired();
}

NodeKind::Type PseudoFile::Content::GetKind() const { return file_->GetKind(); }

zx_status_t PseudoFile::Content::ReadAt(uint64_t count, uint64_t offset,
                                        std::vector<uint8_t>* out_data) {
  if (offset >= buffer_.size()) {
    return ZX_OK;
  }
  size_t actual = std::min(buffer_.size() - offset, count);
  out_data->resize(actual);
  std::copy_n(buffer_.begin() + offset, actual, out_data->begin());
  return ZX_OK;
}

zx_status_t PseudoFile::Content::GetAttr(
    fuchsia::io::NodeAttributes* out_attributes) const {
  return file_->GetAttr(out_attributes);
}

zx_status_t PseudoFile::Content::WriteAt(std::vector<uint8_t> data,
                                         uint64_t offset,
                                         uint64_t* out_actual) {
  if (offset >= file_->max_file_size_) {
    *out_actual = 0u;
    return ZX_OK;
  }

  size_t actual = std::min(data.size(), file_->max_file_size_ - offset);
  if (actual == 0) {
    *out_actual = 0u;
    return ZX_OK;
  }

  dirty_ = true;
  if (actual + offset > buffer_.size()) {
    SetInputLength(offset + actual);
  }

  std::copy_n(data.begin(), actual, buffer_.begin() + offset);
  *out_actual = actual;
  return ZX_OK;
}

zx_status_t PseudoFile::Content::Truncate(uint64_t length) {
  if (length > file_->max_file_size_) {
    return ZX_ERR_NO_SPACE;
  }

  dirty_ = true;
  SetInputLength(length);
  return ZX_OK;
}

uint64_t PseudoFile::Content::GetLength() { return buffer_.size(); }

size_t PseudoFile::Content::GetCapacity() { return file_->max_file_size_; }

void PseudoFile::Content::SetInputLength(size_t length) {
  ZX_ASSERT_MSG(length <= file_->max_file_size_,
                "Should not happen. Please report a bug.");

  buffer_.resize(length);
}

zx_status_t PseudoFile::Content::BindInternal(zx::channel request,
                                              async_dispatcher_t* dispatcher) {
  std::unique_ptr<Connection> connection;
  zx_status_t status = CreateConnection(flags_, &connection);
  if (status != ZX_OK) {
    SendOnOpenEventOnError(flags_, std::move(request), status);
    return status;
  }
  status = connection->Bind(std::move(request), dispatcher);

  AddConnection(std::move(connection));

  // only one connection allowed per content
  ZX_DEBUG_ASSERT(GetConnectionCount() == 1);

  return status;
}

std::unique_ptr<vfs::internal::Connection> PseudoFile::Content::Close(
    Connection* connection) {
  File::Close(connection);
  return file_->Close(this);
}

void PseudoFile::Content::Clone(uint32_t flags, uint32_t parent_flags,
                                zx::channel request,
                                async_dispatcher_t* dispatcher) {
  file_->Clone(flags, parent_flags, std::move(request), dispatcher);
}

void PseudoFile::Content::SendOnOpenEvent(zx_status_t status) {
  // not needed as underlying connection should do this
}

}  // namespace vfs
