// Copyright 2020 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 "src/storage/factory/factoryfs/file.h"

#include <lib/syslog/cpp/macros.h>

namespace factoryfs {

File::File(Factoryfs& factoryfs, std::unique_ptr<DirectoryEntryManager> entry)
    : factoryfs_(factoryfs), directory_entry_(std::move(entry)) {
  factoryfs_.DidOpen(directory_entry_->GetName(), *this);
}

uint32_t File::GetSize() const { return directory_entry_->GetDataSize(); }

std::string_view File::GetName() const { return directory_entry_->GetName(); }

zx_status_t File::InitFileVmo() {
  if (vmo_.is_valid()) {
    return ZX_OK;
  }

  zx_status_t status;
  const size_t vmo_size = fbl::round_up(GetSize(), kFactoryfsBlockSize);
  if ((status = zx::vmo::create(vmo_size, 0, &vmo_)) != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to initialize vmo; error: " << zx_status_get_string(status);
    return status;
  }
  vmo_size_ = vmo_size;

  // TODO(manalib) append filename to make property-name unique for different files.
  zx_object_set_property(vmo_.get(), ZX_PROP_NAME, "factoryfs-file", strlen("factoryfs-file"));

  if ((status = factoryfs_.Device().BlockAttachVmo(vmo_, &vmoid_)) != ZX_OK) {
    FX_LOGS(INFO) << "File::Failed to attach vmo to block device: " << zx_status_get_string(status);
    vmo_.reset();
    return status;
  }

  uint32_t dev_block_size = factoryfs_.GetDeviceBlockInfo().block_size;
  uint32_t dev_blocks =
      fbl::round_up(directory_entry_->GetDataSize(), dev_block_size) / dev_block_size;
  block_fifo_request_t request = {
      .opcode = BLOCKIO_READ,
      .vmoid = vmoid_.get(),
      .length = dev_blocks,
      .vmo_offset = 0,
      .dev_offset = FsToDeviceBlocks(directory_entry_->GetDataStart(), dev_block_size),
  };

  return factoryfs_.Device().FifoTransaction(&request, 1);
}

zx_status_t File::Read(void* data, size_t len, size_t offset, size_t* out_actual) {
  if (data == nullptr || out_actual == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }

  // clip to EOF
  if (offset >= GetSize()) {
    *out_actual = 0;
    return ZX_OK;
  }
  if (len > (GetSize() - offset)) {
    len = GetSize() - offset;
  }

  zx_status_t status = ZX_OK;
  if ((status = InitFileVmo()) != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to initialize VMO error: " << zx_status_get_string(status);
    return status;
  }
  if ((status = vmo_.read(data, offset, len)) != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to read VMO error: " << zx_status_get_string(status);
    return status;
  }
  *out_actual = len;
  return ZX_OK;
}

zx_status_t File::Write(const void* data, size_t len, size_t offset, size_t* out_actual) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t File::Truncate(size_t len) { return ZX_ERR_NOT_SUPPORTED; }

zx_status_t File::GetAttributes(fs::VnodeAttributes* attributes) {
  *attributes = fs::VnodeAttributes();
  attributes->mode = (V_TYPE_FILE | V_IRUSR);
  attributes->content_size = directory_entry_->GetDataSize();
  // There is no concept of inode number in factoryfs
  attributes->inode = fuchsia_io::wire::kInoUnknown;
  attributes->storage_size =
      fbl::round_up<uint32_t>(directory_entry_->GetDataSize(), kFactoryfsBlockSize);
  attributes->link_count = 1;
  // Creation time and modification time for factoryfs should be the same,
  // i.e when exporter formatted the partition last.
  attributes->creation_time = factoryfs_.Info().create_time;
  attributes->modification_time = factoryfs_.Info().create_time;
  return ZX_OK;
}

File::~File() {
  factoryfs_.DidClose(GetName());
  factoryfs_.Device().BlockDetachVmo(std::move(vmoid_));
}

}  // namespace factoryfs
