// Copyright 2021 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 <dirent.h>
#include <sys/stat.h>
#include <stdint.h>
#include <string.h>
#include <sys/stat.h>

#include "f2fs.h"
#include "dir.h"
#include "fbl/auto_lock.h"
#include "file.h"
#include "third_party/f2fs/f2fs_layout.h"
#include "third_party/f2fs/f2fs_lib.h"
#include "zircon/errors.h"
#include "zircon/types.h"

namespace f2fs {

VnodeF2fs::VnodeF2fs(F2fs *fs) : fs_(fs) {}

VnodeF2fs::VnodeF2fs(F2fs *fs, ino_t ino) : fs_(fs), ino_(ino) {}

bool VnodeF2fs::IsDirectory() { return S_ISDIR(inode_.i_mode); }

fs::VnodeProtocolSet VnodeF2fs::GetProtocols() const {
  if (S_ISDIR(inode_.i_mode)) {
    return fs::VnodeProtocol::kDirectory;
  } else {
    return fs::VnodeProtocol::kFile;
  }
}

zx_status_t VnodeF2fs::GetNodeInfoForProtocol([[maybe_unused]] fs::VnodeProtocol protocol,
                                              [[maybe_unused]] fs::Rights rights,
                                              fs::VnodeRepresentation *info) {
  if (IsDirectory()) {
    *info = fs::VnodeRepresentation::Directory();
  } else {
    *info = fs::VnodeRepresentation::File();
  }
  return ZX_OK;
}

void VnodeF2fs::Allocate(F2fs *fs, ino_t ino, uint32_t mode, fbl::RefPtr<VnodeF2fs> *out) {
  /* Check if ino is within scope */
  CheckNidRange(&fs->SbInfo(), ino);

  if (S_ISDIR(mode)) {
    *out = fbl::AdoptRef(new Dir(fs, ino));
  } else {
    *out = fbl::AdoptRef(new File(fs, ino));
  }

  VnodeF2fs *vnode = out->get();

  mtx_init(&vnode->i_mutex, mtx_plain);

  memset(&vnode->fi, 0, sizeof(f2fs_inode_info));

#if 0  // porting needed
  // AtomicSet(&vnode->fi.vfs_inode.i_version, 1);
#endif
  AtomicSet(&vnode->fi.dirty_dents, 0);
  vnode->fi.i_current_depth = 1;
  vnode->fi.i_advise = 0;
  RwlockInit(&vnode->fi.ext.ext_lock);

  SetInodeFlag(&vnode->fi, FI_NEW_INODE);
}

// TODO(sukka): fill vfs->members in addtion to size
// TODO(sukka): if dir/file vnode are defined as different class, check if the ino is for dir/file
void VnodeF2fs::Create(F2fs *fs, ino_t ino, fbl::RefPtr<VnodeF2fs> *out) {
  Page *node_page = nullptr;
  f2fs_inode *ri;
  f2fs_node *rn;

  if (ino == F2FS_NODE_INO(&fs->SbInfo()) || ino == F2FS_META_INO(&fs->SbInfo())) {
    *out = fbl::AdoptRef(new VnodeF2fs(fs, ino));
    return;
  }

  /* Check if ino is within scope */
  CheckNidRange(&fs->SbInfo(), ino);

  if (fs->Nodemgr().GetNodePage(ino, &node_page) != ZX_OK) {
    return;
  }

  rn = static_cast<f2fs_node *>(PageAddress(node_page));
  ri = &(rn->i);

  // [sukka] need to check result?
  if (S_ISDIR(ri->i_mode)) {
    *out = fbl::AdoptRef(new Dir(fs, ino));
  } else {
    *out = fbl::AdoptRef(new File(fs, ino));
  }

  memcpy(&(*out)->inode_, ri, sizeof(f2fs_inode));

  VnodeF2fs *vnode = out->get();

  mtx_init(&vnode->i_mutex, mtx_plain);

  vnode->i_mode = LeToCpu(ri->i_mode);
  vnode->i_uid = LeToCpu(ri->i_uid);
  vnode->i_gid = LeToCpu(ri->i_gid);
  vnode->i_nlink = ri->i_links;
  vnode->i_size = LeToCpu(ri->i_size);
  vnode->i_blocks = LeToCpu(ri->i_blocks);

  vnode->i_atime.tv_sec = LeToCpu(ri->i_atime);
  vnode->i_ctime.tv_sec = LeToCpu(ri->i_ctime);
  vnode->i_mtime.tv_sec = LeToCpu(ri->i_mtime);
  vnode->i_atime.tv_nsec = LeToCpu(ri->i_atime_nsec);
  vnode->i_ctime.tv_nsec = LeToCpu(ri->i_ctime_nsec);
  vnode->i_mtime.tv_nsec = LeToCpu(ri->i_mtime_nsec);
  vnode->i_generation = LeToCpu(ri->i_generation);

  vnode->fi.i_current_depth = LeToCpu(ri->i_current_depth);
  vnode->fi.i_xattr_nid = LeToCpu(ri->i_xattr_nid);
  vnode->fi.i_flags = LeToCpu(ri->i_flags);
  vnode->fi.flags = 0;
#if 0  // porting needed
  // vnode->fi.data_version = LeToCpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
#endif
  vnode->fi.i_advise = ri->i_advise;
  RwlockInit(&vnode->fi.ext.ext_lock);
  GetExtentInfo(&vnode->fi.ext, ri->i_ext);

  fbl::StringPiece name(reinterpret_cast<char *>(ri->i_name), ri->i_namelen);
  vnode->i_name_sp = name;

  F2fsPutPage(node_page, 1);
}

zx_status_t VnodeF2fs::Open([[maybe_unused]] ValidatedOptions options,
                            fbl::RefPtr<Vnode> *out_redirect) {
  fd_count_++;

  return ZX_OK;
}

zx_status_t VnodeF2fs::Close() {
  fd_count_--;

  return ZX_OK;
}

void VnodeF2fs::fbl_recycle() {
  fs_->EraseVnodeFromTable(this);
  delete this;
}

zx_status_t VnodeF2fs::GetAttributes(fs::VnodeAttributes *a) {
#ifdef F2FS_BU_DEBUG
  FX_LOGS(DEBUG) << "f2fs_getattr() vn=" << this << "(#" << ino_ << ")";
#endif
  *a = fs::VnodeAttributes();

  a->mode = i_mode;
  a->inode = ino_;
  a->content_size = i_size;
  a->storage_size = i_blocks * kF2fsBlockSize;
  a->link_count = i_nlink;
  a->creation_time = inode_.i_ctime;
  a->modification_time = inode_.i_mtime;

  return ZX_OK;
}

struct f2fs_iget_args {
  uint64_t ino;
  int on_free;
};

#if 0  // porting needed
// void VnodeF2fs::F2fsSetInodeFlags() {
  // uint64_t &flags = fi.i_flags;

  // inode_.i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE |
  //     S_NOATIME | S_DIRSYNC);

  // if (flags & FS_SYNC_FL)
  //   inode_.i_flags |= S_SYNC;
  // if (flags & FS_APPEND_FL)
  //   inode_.i_flags |= S_APPEND;
  // if (flags & FS_IMMUTABLE_FL)
  //   inode_.i_flags |= S_IMMUTABLE;
  // if (flags & FS_NOATIME_FL)
  //   inode_.i_flags |= S_NOATIME;
  // if (flags & FS_DIRSYNC_FL)
  //   inode_.i_flags |= S_DIRSYNC;
// }

// int VnodeF2fs::F2fsIgetTest(void *data) {
  // f2fs_iget_args *args = (f2fs_iget_args *)data;

  // if (ino_ != args->ino)
  //   return 0;
  // if (i_state & (I_FREEING | I_WILL_FREE)) {
  //   args->on_free = 1;
  //   return 0;
  // }
  // return 1;
// }

// VnodeF2fs *VnodeF2fs::F2fsIgetNowait(uint64_t ino) {
//   fbl::RefPtr<VnodeF2fs> vnode_refptr;
//   VnodeF2fs *vnode = nullptr;
//   f2fs_iget_args args = {.ino = ino, .on_free = 0};
//   vnode = ilookup5(sb, ino, F2fsIgetTest, &args);

//   if (vnode)
//     return vnode;
//   if (!args.on_free) {
//     F2fsVget(Vfs(), ino, &vnode_refptr);
//     vnode = vnode_refptr.get();
//     return vnode;
//   }
//   return static_cast<VnodeF2fs *>(ErrPtr(ZX_ERR_NOT_FOUND));
// }
#endif

zx_status_t VnodeF2fs::F2fsVget(F2fs *fs, uint64_t ino, fbl::RefPtr<VnodeF2fs> *out) {
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode;

  if (fs->FindVnode(&vnode_refptr, ino) == ZX_OK) {
    *out = std::move(vnode_refptr);
    return ZX_OK;
  }

  Create(fs, ino, &vnode_refptr);

  vnode = vnode_refptr.get();

  if (vnode == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  fs->InsertVnode(vnode);

  fbl::AutoLock lock(&vnode->v_lock);

#if 0  // porting needed
  // if (!(vnode->i_state & I_NEW))
  //  return vnode;
#endif

  if (!(ino == F2FS_NODE_INO(&fs->SbInfo()) || ino == F2FS_META_INO(&fs->SbInfo()))) {
    if (!fs->SbInfo().por_doing && vnode->i_nlink == 0) {
#if 0  // porting needed
      // iget_failed(inode);
#endif
      return ZX_ERR_NOT_FOUND;
    }
  }

#if 0  // porting needed
  // if (ino == F2FS_NODE_INO(sbi)) {
  //   // inode->i_mapping->a_ops = &f2fs_node_aops; //invalidatepage, releasepage
  //   // mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
  // } else if (ino == F2FS_META_INO(sbi)) {
  //   // inode->i_mapping->a_ops = &f2fs_meta_aops; //empty
  //   // mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
  // } else if (S_ISREG(inode->i_mode)) {
  //   // inode->i_op = &f2fs_file_inode_operations; //empty
  //   // inode->i_fop = &f2fs_file_operations; //empty
  //   // inode->i_mapping->a_ops = &f2fs_dblock_aops;
  // } else if (S_ISDIR(inode->i_mode)) {
  //   // inode->i_op = &f2fs_dir_inode_operations; //lookup only
  //   // inode->i_fop = &f2fs_dir_operations; //read, readdir
  //   // inode->i_mapping->a_ops = &f2fs_dblock_aops; //readpage, readpages, invalidatepage,
  //   releasepage
  //   // mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE |
  //   //     __GFP_ZERO);
  // } else if (S_ISLNK(inode->i_mode)) {
  //   // inode->i_op = &f2fs_symlink_inode_operations; //empty
  //   // inode->i_mapping->a_ops = &f2fs_dblock_aops;
  // } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
  //     S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
  //   // inode->i_op = &f2fs_special_inode_operations; //empty
  //   init_special_inode(inode, inode->i_mode, inode->i_rdev);
  // } else {
  //     iget_failed(inode);
  //     return ZX_ERR_IO;
  // }
#endif

  *out = std::move(vnode_refptr);

  return ZX_OK;
}

void VnodeF2fs::UpdateInode(Page *node_page) {
  f2fs_node *rn;
  f2fs_inode *ri;

  WaitOnPageWriteback(node_page);

  rn = static_cast<f2fs_node *>(PageAddress(node_page));
  ri = &(rn->i);

  ri->i_mode = CpuToLe(i_mode);
  ri->i_advise = fi.i_advise;
  ri->i_uid = CpuToLe(i_uid);
  ri->i_gid = CpuToLe(i_gid);
  ri->i_links = CpuToLe(i_nlink);
  ri->i_size = CpuToLe(static_cast<uint64_t>(i_size));
  ri->i_blocks = CpuToLe(static_cast<uint64_t>(i_blocks));
  set_raw_extent(&fi.ext, &ri->i_ext);

  ri->i_atime = CpuToLe(static_cast<uint64_t>(i_atime.tv_sec));
  ri->i_ctime = CpuToLe(static_cast<uint64_t>(i_ctime.tv_sec));
  ri->i_mtime = CpuToLe(static_cast<uint64_t>(i_mtime.tv_sec));
  ri->i_atime_nsec = CpuToLe(static_cast<uint32_t>(i_atime.tv_nsec));
  ri->i_ctime_nsec = CpuToLe(static_cast<uint32_t>(i_ctime.tv_nsec));
  ri->i_mtime_nsec = CpuToLe(static_cast<uint64_t>(i_mtime.tv_nsec));
  ri->i_current_depth = CpuToLe(fi.i_current_depth);
  ri->i_xattr_nid = CpuToLe(fi.i_xattr_nid);
  ri->i_flags = CpuToLe(fi.i_flags);
  ri->i_generation = CpuToLe(i_generation);
#if 0  // porting needed
  // set_page_dirty(node_page);
#else
  FlushDirtyNodePage(Vfs(), node_page);
#endif
}

int VnodeF2fs::F2fsWriteInode(WritebackControl *wbc) TA_NO_THREAD_SAFETY_ANALYSIS {
  f2fs_sb_info &sbi = Vfs()->SbInfo();
  Page *node_page = nullptr;
  zx_status_t ret = ZX_OK;

  if (ino_ == F2FS_NODE_INO(&sbi) || ino_ == F2FS_META_INO(&sbi))
    return ret;

  if (ret = Vfs()->Nodemgr().GetNodePage(ino_, &node_page); ret != ZX_OK)
    return ret;

  if (PageDirty(node_page)) {
    UpdateInode(node_page);
    F2fsPutPage(node_page, 1);
  } else {
    F2fsPutPage(node_page, 1);
    fbl::AutoLock lock(&sbi.write_inode);
    if (ret = Vfs()->Nodemgr().GetNodePage(ino_, &node_page); ret != ZX_OK)
      return ret;
    UpdateInode(node_page);
    F2fsPutPage(node_page, 1);
  }

  return ZX_OK;
}

#if 0  // porting needed
// void VnodeF2fs::F2fsTruncate() {
//   if (!(S_ISREG(i_mode) || S_ISDIR(i_mode) || S_ISLNK(i_mode)))
//     return;

//   if (!TruncateBlocks(i_size)) {
//     auto cur_time = time(nullptr);
//     i_mtime.tv_sec = cur_time;
//     i_mtime.tv_nsec = 0;
//     i_ctime.tv_sec = cur_time;
//     i_ctime.tv_nsec = 0;
//     MarkInodeDirty(this);
//   }

//   Vfs()->Segmgr().F2fsBalanceFs();
// }
#endif

int VnodeF2fs::TruncateDataBlocksRange(dnode_of_data *dn, int count) {
  int nr_free = 0, ofs = dn->ofs_in_node;
  f2fs_sb_info &sbi = Vfs()->SbInfo();
  f2fs_node *raw_node;
  uint32_t *addr;

  raw_node = static_cast<f2fs_node *>(PageAddress(dn->node_page));
  addr = blkaddr_in_node(raw_node) + ofs;

  for (; count > 0; count--, addr++, dn->ofs_in_node++) {
    block_t blkaddr = LeToCpu(*addr);
    if (blkaddr == NULL_ADDR)
      continue;

    UpdateExtentCache(NULL_ADDR, dn);
    Vfs()->Segmgr().InvalidateBlocks(blkaddr);
    dec_valid_block_count(&sbi, dn->vnode, 1);
    nr_free++;
  }
  if (nr_free) {
#if 0  // porting needed
    // set_page_dirty(dn->node_page);
#else
    FlushDirtyNodePage(Vfs(), dn->node_page);
#endif
    Vfs()->Nodemgr().SyncInodePage(dn);
  }
  dn->ofs_in_node = ofs;
  return nr_free;
}

void VnodeF2fs::TruncateDataBlocks(dnode_of_data *dn) {
  TruncateDataBlocksRange(dn, ADDRS_PER_BLOCK);
}

void VnodeF2fs::TruncatePartialDataPage(uint64_t from) {
  unsigned offset = from & (kPageCacheSize - 1);
  Page *page = nullptr;

  if (!offset)
    return;

  if (FindDataPage(from >> kPageCacheShift, &page) != ZX_OK)
    return;

#if 0  // porting needed
  // lock_page(page);
#endif
  WaitOnPageWriteback(page);
  zero_user(page, offset, kPageCacheSize - offset);
#if 0  // porting needed
  // set_page_dirty(page);
#else
  FlushDirtyDataPage(Vfs(), page);
#endif
  F2fsPutPage(page, 1);
}

#if 0  // porting needed
// int VnodeF2fs::TruncateBlocks(uint64_t from) {
//   f2fs_sb_info &sbi = Vfs()->SbInfo();
//   unsigned int blocksize = sbi.blocksize;
//   dnode_of_data dn;
//   pgoff_t free_from;
//   int count = 0;
//   int err;

//   free_from = (pgoff_t)((from + blocksize - 1) >> (sbi.log_blocksize));

//   mutex_lock_op(&sbi, DATA_TRUNC);

//   SetNewDnode(&dn, this, NULL, NULL, 0);
//   err = Vfs()->Nodemgr().GetDnodeOfData(&dn, free_from, RDONLY_NODE);
//   if (err) {
//     if (err == ZX_ERR_NOT_FOUND)
//       goto free_next;
//     mutex_unlock_op(&sbi, DATA_TRUNC);
//     return err;
//   }

//   if (IS_INODE(dn.node_page))
//     count = ADDRS_PER_INODE;
//   else
//     count = ADDRS_PER_BLOCK;

//   count -= dn.ofs_in_node;
//   BUG_ON(count < 0);
//   if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
//     TruncateDataBlocksRange(&dn, count);
//     free_from += count;
//   }

//   F2fsPutDnode(&dn);
// free_next:
//   err = Vfs()->Nodemgr().TruncateInodeBlocks(this, free_from);
//   mutex_unlock_op(&sbi, DATA_TRUNC);

//   /* lastly zero out the first data page */
//   TruncatePartialDataPage(from);

//   return err;
// }
#endif

int VnodeF2fs::TruncateHole(pgoff_t pg_start, pgoff_t pg_end) {
  pgoff_t index;

  for (index = pg_start; index < pg_end; index++) {
    dnode_of_data dn;
    f2fs_sb_info &sbi = Vfs()->SbInfo();

    fbl::AutoLock lock(&sbi.fs_lock[DATA_TRUNC]);
    SetNewDnode(&dn, this, NULL, NULL, 0);
    if (zx_status_t err = Vfs()->Nodemgr().GetDnodeOfData(&dn, index, RDONLY_NODE); err != ZX_OK) {
      if (err == ZX_ERR_NOT_FOUND)
        continue;
      return err;
    }

    if (dn.data_blkaddr != NULL_ADDR)
      TruncateDataBlocksRange(&dn, 1);
    F2fsPutDnode(&dn);
  }
  return 0;
}

/**
 * Called at the last Iput() if i_nlink is zero
 */
#if 0  // porting needed
// void VnodeF2fs::F2fsEvictInode() {
//   f2fs_sb_info &sbi = Vfs()->SbInfo();

//   // truncate_inode_pages(&inode->i_data, 0);

//   if (ino_ == F2FS_NODE_INO(&sbi) || ino_ == F2FS_META_INO(&sbi))
//     goto no_delete;

//   // BUG_ON(AtomicRead(&fi.->dirty_dents));
//   // remove_dirty_dir_inode(this);

//   if (i_nlink || IsBadInode(this))
//     goto no_delete;

//   SetInodeFlag(&fi, FI_NO_ALLOC);
//   i_size = 0;

//   if (F2FS_HAS_BLOCKS(this))
//     F2fsTruncate();

//   // remove_inode_page(inode);
// no_delete:
//   ClearInode(this);
// }
#endif

void VnodeF2fs::IncNlink() { i_nlink++; }

void VnodeF2fs::DropNlink() { i_nlink--; }

void VnodeF2fs::ClearNlink() { i_nlink = 0; }

void VnodeF2fs::SetNlink(uint32_t nlink) { i_nlink = nlink; }

void MarkInodeDirty(VnodeF2fs *vnode) { vnode->F2fsWriteInode(nullptr); }

void VnodeF2fs::Sync(SyncCallback closure) {
	File *file;

  if (closure) {
    if (S_ISDIR(this->i_mode)) {
      std::cout << "Sync: Invalid args(fsync to directory)" << std::endl;
      closure(ZX_ERR_INVALID_ARGS);
    } else {
      file = static_cast<File *>(this);
      file->F2fsSyncFile(0, file->i_size, 1);
      closure(ZX_OK);
    }
  }
}

zx_status_t VnodeF2fs::QueryFilesystem(::fuchsia_io::wire::FilesystemInfo *info) {
  f2fs_sb_info &sbi = Vfs()->SbInfo();
  *info = {};
  info->block_size = kF2fsBlockSize;
  info->max_filename_size = F2FS_MAX_NAME_LEN;
  info->fs_type = VFS_TYPE_F2FS;
  info->fs_id = Vfs()->FsId();
  info->total_bytes = sbi.user_block_count * kF2fsBlockSize;
  info->used_bytes = valid_user_blocks(&sbi) * kF2fsBlockSize;
  info->total_nodes = sbi.total_node_count;
  info->used_nodes = sbi.total_valid_inode_count;

  constexpr std::string_view kFsName = "f2fs";
  static_assert(kFsName.size() + 1 < ::fuchsia_io::wire::MAX_FS_NAME_BUFFER, "F2fs name too long");
  info->name[kFsName.copy(reinterpret_cast<char *>(info->name.data()),
                          ::fuchsia_io::wire::MAX_FS_NAME_BUFFER - 1)] = '\0';

  // TODO(unknown): Fill info->free_shared_pool_bytes using fvm info

  return ZX_OK;
}

}  // namespace f2fs
