// 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/vfs/cpp/pseudo_file.h>

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

#include <sstream>

namespace vfs {

BufferedPseudoFile::BufferedPseudoFile(ReadHandler read_handler,
                                       WriteHandler write_handler,
                                       size_t buffer_capacity)
    : read_handler_(std::move(read_handler)),
      write_handler_(std::move(write_handler)),
      buffer_capacity_(buffer_capacity) {
  ZX_DEBUG_ASSERT(read_handler_ != nullptr);
}

BufferedPseudoFile::~BufferedPseudoFile() = default;

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

uint32_t BufferedPseudoFile::GetAdditionalAllowedFlags() const {
  auto allowed_flags = fuchsia::io::OPEN_RIGHT_READABLE;
  if (write_handler_ != nullptr) {
    allowed_flags |=
        fuchsia::io::OPEN_RIGHT_WRITABLE | fuchsia::io::OPEN_FLAG_TRUNCATE;
  }
  return allowed_flags;
}

uint32_t BufferedPseudoFile::GetProhibitiveFlags() const {
  return fuchsia::io::OPEN_FLAG_APPEND;
}

uint64_t BufferedPseudoFile::GetLength() {
  // this should never be called
  ZX_DEBUG_ASSERT(false);

  return 0u;
}

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

  return buffer_capacity_;
}

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

BufferedPseudoFile::Content::~Content() {
  if (!dirty_) {
    return;
  }
  file_->write_handler_(std::move(buffer_));
};

zx_status_t BufferedPseudoFile::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;
}

uint32_t BufferedPseudoFile::Content::GetAdditionalAllowedFlags() const {
  return file_->GetAdditionalAllowedFlags();
}

uint32_t BufferedPseudoFile::Content::GetProhibitiveFlags() const {
  return file_->GetProhibitiveFlags();
}

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

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

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

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

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

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

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

size_t BufferedPseudoFile::Content::GetCapacity() {
  return file_->buffer_capacity_;
}

void BufferedPseudoFile::Content::SetInputLength(size_t length) {
  ZX_DEBUG_ASSERT(length <= file_->buffer_capacity_);

  buffer_.resize(length);
}

zx_status_t BufferedPseudoFile::Content::Bind(zx::channel request,
                                              async_dispatcher_t* dispatcher) {
  // only one connection allowed per content
  ZX_DEBUG_ASSERT(connections().size() == 0);

  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));
  return status;
}

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

void BufferedPseudoFile::Content::SendOnOpenEvent(zx_status_t status) {
  ZX_DEBUG_ASSERT(connections().size() == 1);

  connections()[0]->SendOnOpenEvent(status);
}

}  // namespace vfs