// Copyright 2018 The Chromium OS 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 "smbprovider/file_copy_progress.h"

#include <algorithm>

#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>

namespace smbprovider {
namespace {

const off_t kDefaultIterationChunkSize = 4 * 1024 * 1024;

}  // namespace

FileCopyProgress::FileCopyProgress(SambaInterface* samba_interface,
                                   off_t iteration_chunk_size)
    : samba_interface_(samba_interface),
      iteration_chunk_size_(iteration_chunk_size) {}

FileCopyProgress::FileCopyProgress(SambaInterface* samba_interface)
    : FileCopyProgress(samba_interface, kDefaultIterationChunkSize) {}

FileCopyProgress::~FileCopyProgress() = default;

bool FileCopyProgress::StartCopy(const std::string& source,
                                 const std::string& target,
                                 int32_t* error) {
  DCHECK(!is_started_);
  is_started_ = true;

  if (!OpenCopySource(source, error) || !OpenCopyTarget(target, error)) {
    FinishCopy();
    return false;
  }

  struct stat source_stat;
  const int32_t stat_result =
      samba_interface_->GetEntryStatus(source, &source_stat);
  if (stat_result != 0) {
    FinishCopy();

    *error = stat_result;
    return false;
  }

  if (source_stat.st_size == 0) {
    // Empty file.
    FinishCopy();

    *error = 0;
    return false;
  }

  bytes_remaining_ = source_stat.st_size;

  return ContinueCopy(error);
}

bool FileCopyProgress::ContinueCopy(int32_t* error) {
  DCHECK(is_started_);
  DCHECK(!is_done_);

  const off_t bytes_to_splice =
      std::min(bytes_remaining_, iteration_chunk_size_);

  DCHECK_GT(bytes_to_splice, 0);
  off_t bytes_spliced;
  int32_t result = samba_interface_->SpliceFile(
      source_fd_, target_fd_, bytes_to_splice, &bytes_spliced);

  if (result != 0) {
    // The copy failed.
    FinishCopy();

    *error = result;
    return false;
  }

  DCHECK_GE(bytes_remaining_, bytes_spliced);
  bytes_remaining_ -= bytes_spliced;

  if (bytes_remaining_ == 0) {
    // The copy is done.
    FinishCopy();

    *error = 0;
    return false;
  }

  // No error and there are |bytes_remaining_| so the copy should be continued.
  return true;
}

bool FileCopyProgress::OpenCopySource(const std::string& file_path,
                                      int32_t* error) {
  *error = samba_interface_->OpenFile(file_path, O_RDONLY, &source_fd_);
  if (*error != 0) {
    return false;
  }
  return true;
}

bool FileCopyProgress::OpenCopyTarget(const std::string& file_path,
                                      int32_t* error) {
  *error = samba_interface_->CreateFile(file_path, &target_fd_);
  if (*error != 0) {
    return false;
  }
  return true;
}

void FileCopyProgress::CloseCopySourceAndTarget() {
  int32_t result;
  if (source_fd_ >= 0) {
    result = samba_interface_->CloseFile(source_fd_);
  }
  if (target_fd_ >= 0) {
    result = samba_interface_->CloseFile(target_fd_);
  }
}

void FileCopyProgress::FinishCopy() {
  is_done_ = true;
  CloseCopySourceAndTarget();
}

}  // namespace smbprovider
