// Copyright 2017 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 <inttypes.h>
#include <sys/stat.h>

#include <algorithm>
#include <thread>
#include <utility>
#include <vector>

#include <blobfs/fsck.h>
#include <fbl/auto_call.h>

#include "blobfs.h"

namespace {

// Add the blob described by |info| on host to the |blobfs| blobfs store.
zx_status_t AddBlob(blobfs::Blobfs* blobfs, FileSizeRecorder* size_recorder,
                    const blobfs::MerkleInfo& info) {
  const char* path = info.path.c_str();
  fbl::unique_fd data_fd(open(path, O_RDONLY, 0644));
  if (!data_fd) {
    fprintf(stderr, "error: cannot open '%s'\n", path);
    return ZX_ERR_IO;
  }
  zx_status_t status =
      blobfs::blobfs_add_blob_with_merkle(blobfs, size_recorder, data_fd.get(), info);
  if (status != ZX_OK && status != ZX_ERR_ALREADY_EXISTS) {
    fprintf(stderr, "blobfs: Failed to add blob '%s': %d\n", path, status);
    return status;
  }
  return ZX_OK;
}

}  // namespace

zx_status_t BlobfsCreator::Usage() {
  zx_status_t status = FsCreator::Usage();

  // Additional information about manifest format.
  fprintf(stderr, "\nEach manifest line must adhere to one of the following formats:\n");
  fprintf(stderr, "\t'dst/path=src/path'\n");
  fprintf(stderr, "\t'dst/path'\n");
  fprintf(stderr, "with one dst/src pair or single dst per line.\n");
  return status;
}

bool BlobfsCreator::IsCommandValid(Command command) {
  switch (command) {
    case Command::kMkfs:
    case Command::kFsck:
    case Command::kUsedDataSize:
    case Command::kUsedInodes:
    case Command::kUsedSize:
    case Command::kAdd:
      return true;
    default:
      return false;
  }
}

bool BlobfsCreator::IsOptionValid(Option option) {
  // TODO(planders): Add offset and length support to blobfs.
  switch (option) {
    case Option::kDepfile:
    case Option::kReadonly:
    case Option::kCompress:
    case Option::kSizes:
    case Option::kHelp:
      return true;
    default:
      return false;
  }
}

bool BlobfsCreator::IsArgumentValid(Argument argument) {
  switch (argument) {
    case Argument::kManifest:
    case Argument::kBlob:
      return true;
    default:
      return false;
  }
}

zx_status_t BlobfsCreator::ProcessManifestLine(FILE* manifest, const char* dir_path) {
  char src[PATH_MAX];
  src[0] = '\0';
  char dst[PATH_MAX];
  dst[0] = '\0';

  zx_status_t status;
  if ((status = ParseManifestLine(manifest, dir_path, &src[0], &dst[0])) != ZX_OK) {
    return status;
  }

  if (!strlen(src)) {
    fprintf(stderr, "Manifest line must specify source file\n");
    return ZX_ERR_INVALID_ARGS;
  }

  blob_list_.push_back(src);
  return ZX_OK;
}

zx_status_t BlobfsCreator::ProcessCustom(int argc, char** argv, uint8_t* processed) {
  constexpr uint8_t required_args = 2;
  if (strcmp(argv[0], "--blob")) {
    fprintf(stderr, "Argument not found: %s\n", argv[0]);
    return ZX_ERR_INVALID_ARGS;
  } else if (argc < required_args) {
    fprintf(stderr, "Not enough arguments for %s\n", argv[0]);
    return ZX_ERR_INVALID_ARGS;
  }

  blob_list_.push_back(argv[1]);
  *processed = required_args;
  return ZX_OK;
}

zx_status_t BlobfsCreator::CalculateRequiredSize(off_t* out) {
  std::vector<std::thread> threads;
  unsigned blob_index = 0;
  unsigned n_threads = std::thread::hardware_concurrency();
  if (!n_threads) {
    n_threads = 4;
  }
  zx_status_t status = ZX_OK;
  std::mutex mtx;
  for (unsigned j = n_threads; j > 0; j--) {
    threads.push_back(std::thread([&] {
      unsigned i = 0;
      while (true) {
        mtx.lock();
        if (status != ZX_OK) {
          mtx.unlock();
          return;
        }
        i = blob_index++;
        mtx.unlock();
        if (i >= blob_list_.size()) {
          return;
        }
        const char* path = blob_list_[i].c_str();
        zx_status_t res;
        if ((res = AppendDepfile(path)) != ZX_OK) {
          mtx.lock();
          status = res;
          mtx.unlock();
          return;
        }

        blobfs::MerkleInfo info;
        fbl::unique_fd data_fd(open(path, O_RDONLY, 0644));

        if ((res = blobfs::blobfs_preprocess(data_fd.get(), ShouldCompress(), &info)) != ZX_OK) {
          mtx.lock();
          status = res;
          mtx.unlock();
          return;
        }

        info.path = path;

        mtx.lock();
        merkle_list_.push_back(std::move(info));
        mtx.unlock();
      }
    }));
  }

  for (unsigned i = 0; i < threads.size(); i++) {
    threads[i].join();
  }

  if (status != ZX_OK) {
    return status;
  }

  // Remove all duplicate blobs by first sorting the merkle trees by
  // digest, and then by reshuffling the vector to exclude duplicates.
  std::sort(merkle_list_.begin(), merkle_list_.end(), DigestCompare());
  auto compare = [](const blobfs::MerkleInfo& lhs, const blobfs::MerkleInfo& rhs) {
    return lhs.digest == rhs.digest;
  };
  auto it = std::unique(merkle_list_.begin(), merkle_list_.end(), compare);
  merkle_list_.resize(std::distance(merkle_list_.begin(), it));

  for (const auto& info : merkle_list_) {
    blobfs::Inode node;
    node.blob_size = info.length;
    data_blocks_ += MerkleTreeBlocks(node) + info.GetDataBlocks();
  }

  blobfs::Superblock info;
  info.inode_count = blobfs::kBlobfsDefaultInodeCount;

  info.data_block_count = data_blocks_;
  info.journal_block_count = blobfs::kDefaultJournalBlocks;
  *out = blobfs::TotalBlocks(info) * blobfs::kBlobfsBlockSize;
  return ZX_OK;
}

zx_status_t BlobfsCreator::Mkfs() {
  uint64_t block_count;
  if (blobfs::GetBlockCount(fd_.get(), &block_count)) {
    fprintf(stderr, "blobfs: cannot find end of underlying device\n");
    return ZX_ERR_IO;
  }

  int r = blobfs::Mkfs(fd_.get(), block_count);

  if (r >= 0 && !blob_list_.is_empty()) {
    zx_status_t status;
    if ((status = Add()) != ZX_OK) {
      return status;
    }
  }
  return r;
}

zx_status_t BlobfsCreator::Fsck() {
  zx_status_t status;
  fbl::unique_ptr<blobfs::Blobfs> vn;
  if ((status = blobfs::blobfs_create(&vn, std::move(fd_))) < 0) {
    return status;
  }

  bool apply_journal = false;
  return blobfs::Fsck(std::move(vn), apply_journal);
}

zx_status_t BlobfsCreator::UsedDataSize() {
  zx_status_t status;
  uint64_t size;
  if ((status = blobfs::UsedDataSize(fd_, &size)) != ZX_OK) {
    return status;
  }

  printf("%" PRIu64 "\n", size);
  return ZX_OK;
}

zx_status_t BlobfsCreator::UsedInodes() {
  zx_status_t status;
  uint64_t used_inodes;
  if ((status = blobfs::UsedInodes(fd_, &used_inodes)) != ZX_OK) {
    return status;
  }

  printf("%" PRIu64 "\n", used_inodes);
  return ZX_OK;
}

zx_status_t BlobfsCreator::UsedSize() {
  zx_status_t status;
  uint64_t size;
  if ((status = blobfs::UsedSize(fd_, &size)) != ZX_OK) {
    return status;
  }

  printf("%" PRIu64 "\n", size);
  return ZX_OK;
}

zx_status_t BlobfsCreator::Add() {
  if (blob_list_.is_empty()) {
    fprintf(stderr, "Adding a blob requires an additional file argument\n");
    return Usage();
  }

  zx_status_t status = ZX_OK;
  fbl::unique_ptr<blobfs::Blobfs> blobfs;
  if ((status = blobfs_create(&blobfs, std::move(fd_))) != ZX_OK) {
    return status;
  }

  std::vector<std::thread> threads;
  std::mutex mtx;

  unsigned n_threads = std::thread::hardware_concurrency();
  if (!n_threads) {
    n_threads = 4;
  }
  unsigned blob_index = 0;
  for (unsigned j = n_threads; j > 0; j--) {
    threads.push_back(std::thread([&] {
      unsigned i = 0;
      while (true) {
        mtx.lock();
        i = blob_index++;
        if (i >= merkle_list_.size()) {
          mtx.unlock();
          return;
        }
        mtx.unlock();

        zx_status_t res;
        if ((res = AddBlob(blobfs.get(), size_recorder(), merkle_list_[i])) < 0) {
          mtx.lock();
          status = res;
          mtx.unlock();
          return;
        }
      }
    }));
  }

  for (unsigned i = 0; i < threads.size(); i++) {
    threads[i].join();
  }

  return status;
}

int main(int argc, char** argv) {
  BlobfsCreator blobfs;

  if (blobfs.ProcessAndRun(argc, argv) != ZX_OK) {
    return -1;
  }

  return 0;
}
