// Copyright (c) 2012 The Chromium 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 "components/drive/file_system/copy_operation.h"

#include <string>

#include "base/task_runner_util.h"
#include "components/drive/drive.pb.h"
#include "components/drive/drive_api_util.h"
#include "components/drive/file_cache.h"
#include "components/drive/file_change.h"
#include "components/drive/file_system/create_file_operation.h"
#include "components/drive/file_system/operation_delegate.h"
#include "components/drive/file_system_core_util.h"
#include "components/drive/job_scheduler.h"
#include "components/drive/resource_entry_conversion.h"
#include "components/drive/resource_metadata.h"
#include "google_apis/drive/drive_api_parser.h"

namespace drive {
namespace file_system {

struct CopyOperation::CopyParams {
  base::FilePath src_file_path;
  base::FilePath dest_file_path;
  bool preserve_last_modified;
  FileOperationCallback callback;
  ResourceEntry src_entry;
  ResourceEntry parent_entry;
};

// Enum for categorizing where a gdoc represented by a JSON file exists.
enum JsonGdocLocationType {
  NOT_IN_METADATA,
  IS_ORPHAN,
  HAS_PARENT,
};

struct CopyOperation::TransferJsonGdocParams {
  TransferJsonGdocParams(const FileOperationCallback& callback,
                         const std::string& resource_id,
                         const ResourceEntry& parent_entry,
                         const std::string& new_title)
      : callback(callback),
        resource_id(resource_id),
        parent_resource_id(parent_entry.resource_id()),
        parent_local_id(parent_entry.local_id()),
        new_title(new_title),
        location_type(NOT_IN_METADATA) {
  }
  // Parameters supplied or calculated from operation arguments.
  const FileOperationCallback callback;
  const std::string resource_id;
  const std::string parent_resource_id;
  const std::string parent_local_id;
  const std::string new_title;

  // Values computed during operation.
  JsonGdocLocationType location_type;  // types where the gdoc file is located.
  std::string local_id;  // the local_id of the file (if exists in metadata.)
  base::FilePath changed_path;
};

namespace {

FileError TryToCopyLocally(internal::ResourceMetadata* metadata,
                           internal::FileCache* cache,
                           CopyOperation::CopyParams* params,
                           std::vector<std::string>* updated_local_ids,
                           bool* directory_changed,
                           bool* should_copy_on_server) {
  FileError error = metadata->GetResourceEntryByPath(params->src_file_path,
                                                     &params->src_entry);
  if (error != FILE_ERROR_OK)
    return error;

  error = metadata->GetResourceEntryByPath(params->dest_file_path.DirName(),
                                           &params->parent_entry);
  if (error != FILE_ERROR_OK)
    return error;

  if (!params->parent_entry.file_info().is_directory())
    return FILE_ERROR_NOT_A_DIRECTORY;

  // Drive File System doesn't support recursive copy.
  if (params->src_entry.file_info().is_directory())
    return FILE_ERROR_NOT_A_FILE;

  // Check destination.
  ResourceEntry dest_entry;
  error = metadata->GetResourceEntryByPath(params->dest_file_path, &dest_entry);
  switch (error) {
    case FILE_ERROR_OK:
      // File API spec says it is an error to try to "copy a file to a path
      // occupied by a directory".
      if (dest_entry.file_info().is_directory())
        return FILE_ERROR_INVALID_OPERATION;

      // Move the existing entry to the trash.
      dest_entry.set_parent_local_id(util::kDriveTrashDirLocalId);
      error = metadata->RefreshEntry(dest_entry);
      if (error != FILE_ERROR_OK)
        return error;
      updated_local_ids->push_back(dest_entry.local_id());
      *directory_changed = true;
      break;
    case FILE_ERROR_NOT_FOUND:
      break;
    default:
      return error;
  }

  // If the cache file is not present and the entry exists on the server,
  // server side copy should be used.
  if (!params->src_entry.file_specific_info().cache_state().is_present() &&
      !params->src_entry.resource_id().empty()) {
    *should_copy_on_server = true;
    return FILE_ERROR_OK;
  }

  // Copy locally.
  ResourceEntry entry;
  const int64 now = base::Time::Now().ToInternalValue();
  entry.set_title(params->dest_file_path.BaseName().AsUTF8Unsafe());
  entry.set_parent_local_id(params->parent_entry.local_id());
  entry.mutable_file_specific_info()->set_content_mime_type(
      params->src_entry.file_specific_info().content_mime_type());
  entry.set_metadata_edit_state(ResourceEntry::DIRTY);
  entry.set_modification_date(base::Time::Now().ToInternalValue());
  entry.mutable_file_info()->set_last_modified(
      params->preserve_last_modified ?
      params->src_entry.file_info().last_modified() : now);
  entry.mutable_file_info()->set_last_accessed(now);

  std::string local_id;
  error = metadata->AddEntry(entry, &local_id);
  if (error != FILE_ERROR_OK)
    return error;
  updated_local_ids->push_back(local_id);
  *directory_changed = true;

  if (!params->src_entry.file_specific_info().cache_state().is_present()) {
    DCHECK(params->src_entry.resource_id().empty());
    // Locally created empty file may have no cache file.
    return FILE_ERROR_OK;
  }

  base::FilePath cache_file_path;
  error = cache->GetFile(params->src_entry.local_id(), &cache_file_path);
  if (error != FILE_ERROR_OK)
    return error;

  return cache->Store(local_id, std::string(), cache_file_path,
                      internal::FileCache::FILE_OPERATION_COPY);
}

// Stores the entry returned from the server and returns its path.
FileError UpdateLocalStateForServerSideOperation(
    internal::ResourceMetadata* metadata,
    scoped_ptr<google_apis::FileResource> file_resource,
    ResourceEntry* entry,
    base::FilePath* file_path) {
  DCHECK(file_resource);

  std::string parent_resource_id;
  if (!ConvertFileResourceToResourceEntry(
          *file_resource, entry, &parent_resource_id) ||
      parent_resource_id.empty())
    return FILE_ERROR_NOT_A_FILE;

  std::string parent_local_id;
  FileError error = metadata->GetIdByResourceId(parent_resource_id,
                                                &parent_local_id);
  if (error != FILE_ERROR_OK)
    return error;
  entry->set_parent_local_id(parent_local_id);

  std::string local_id;
  error = metadata->AddEntry(*entry, &local_id);
  // Depending on timing, the metadata may have inserted via change list
  // already. So, FILE_ERROR_EXISTS is not an error.
  if (error == FILE_ERROR_EXISTS)
    error = metadata->GetIdByResourceId(entry->resource_id(), &local_id);

  if (error != FILE_ERROR_OK)
    return error;

  return metadata->GetFilePath(local_id, file_path);
}

// Stores the file at |local_file_path| to the cache as a content of entry at
// |remote_dest_path|, and marks it dirty.
FileError UpdateLocalStateForScheduleTransfer(
    internal::ResourceMetadata* metadata,
    internal::FileCache* cache,
    const base::FilePath& local_src_path,
    const base::FilePath& remote_dest_path,
    ResourceEntry* entry,
    std::string* local_id) {
  FileError error = metadata->GetIdByPath(remote_dest_path, local_id);
  if (error != FILE_ERROR_OK)
    return error;

  error = metadata->GetResourceEntryById(*local_id, entry);
  if (error != FILE_ERROR_OK)
    return error;

  return cache->Store(*local_id, std::string(), local_src_path,
                      internal::FileCache::FILE_OPERATION_COPY);
}

// Gets the file size of the |local_path|, and the ResourceEntry for the parent
// of |remote_path| to prepare the necessary information for transfer.
FileError PrepareTransferFileFromLocalToRemote(
    internal::ResourceMetadata* metadata,
    const base::FilePath& local_src_path,
    const base::FilePath& remote_dest_path,
    std::string* gdoc_resource_id,
    ResourceEntry* parent_entry) {
  FileError error = metadata->GetResourceEntryByPath(
      remote_dest_path.DirName(), parent_entry);
  if (error != FILE_ERROR_OK)
    return error;

  // The destination's parent must be a directory.
  if (!parent_entry->file_info().is_directory())
    return FILE_ERROR_NOT_A_DIRECTORY;

  // Try to parse GDoc File and extract the resource id, if necessary.
  // Failing isn't problem. It'd be handled as a regular file, then.
  if (util::HasHostedDocumentExtension(local_src_path))
    *gdoc_resource_id = util::ReadResourceIdFromGDocFile(local_src_path);
  return FILE_ERROR_OK;
}

// Performs local work before server-side work for transferring JSON-represented
// gdoc files.
FileError LocalWorkForTransferJsonGdocFile(
    internal::ResourceMetadata* metadata,
    CopyOperation::TransferJsonGdocParams* params) {
  std::string local_id;
  FileError error = metadata->GetIdByResourceId(params->resource_id, &local_id);
  if (error != FILE_ERROR_OK) {
    params->location_type = NOT_IN_METADATA;
    return error == FILE_ERROR_NOT_FOUND ? FILE_ERROR_OK : error;
  }

  ResourceEntry entry;
  error = metadata->GetResourceEntryById(local_id, &entry);
  if (error != FILE_ERROR_OK)
    return error;
  params->local_id = entry.local_id();

  if (entry.parent_local_id() == util::kDriveOtherDirLocalId) {
    params->location_type = IS_ORPHAN;
    entry.set_title(params->new_title);
    entry.set_parent_local_id(params->parent_local_id);
    entry.set_metadata_edit_state(ResourceEntry::DIRTY);
    entry.set_modification_date(base::Time::Now().ToInternalValue());
    error = metadata->RefreshEntry(entry);
    if (error != FILE_ERROR_OK)
      return error;
    return metadata->GetFilePath(local_id, &params->changed_path);
  }

  params->location_type = HAS_PARENT;
  return FILE_ERROR_OK;
}

}  // namespace

CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner,
                             OperationDelegate* delegate,
                             JobScheduler* scheduler,
                             internal::ResourceMetadata* metadata,
                             internal::FileCache* cache)
  : blocking_task_runner_(blocking_task_runner),
    delegate_(delegate),
    scheduler_(scheduler),
    metadata_(metadata),
    cache_(cache),
    create_file_operation_(new CreateFileOperation(blocking_task_runner,
                                                   delegate,
                                                   metadata)),
    weak_ptr_factory_(this) {
}

CopyOperation::~CopyOperation() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void CopyOperation::Copy(const base::FilePath& src_file_path,
                         const base::FilePath& dest_file_path,
                         bool preserve_last_modified,
                         const FileOperationCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  CopyParams* params = new CopyParams;
  params->src_file_path = src_file_path;
  params->dest_file_path = dest_file_path;
  params->preserve_last_modified = preserve_last_modified;
  params->callback = callback;

  std::vector<std::string>* updated_local_ids = new std::vector<std::string>;
  bool* directory_changed = new bool(false);
  bool* should_copy_on_server = new bool(false);
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&TryToCopyLocally, metadata_, cache_, params,
                 updated_local_ids, directory_changed, should_copy_on_server),
      base::Bind(&CopyOperation::CopyAfterTryToCopyLocally,
                 weak_ptr_factory_.GetWeakPtr(), base::Owned(params),
                 base::Owned(updated_local_ids), base::Owned(directory_changed),
                 base::Owned(should_copy_on_server)));
}

void CopyOperation::CopyAfterTryToCopyLocally(
    const CopyParams* params,
    const std::vector<std::string>* updated_local_ids,
    const bool* directory_changed,
    const bool* should_copy_on_server,
    FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!params->callback.is_null());

  for (const auto& id : *updated_local_ids) {
    // Syncing for copy should be done in background, so pass the BACKGROUND
    // context. See: crbug.com/420278.
    delegate_->OnEntryUpdatedByOperation(ClientContext(BACKGROUND), id);
  }

  if (*directory_changed) {
    FileChange changed_file;
    DCHECK(!params->src_entry.file_info().is_directory());
    changed_file.Update(params->dest_file_path, FileChange::FILE_TYPE_FILE,
                        FileChange::CHANGE_TYPE_ADD_OR_UPDATE);
    delegate_->OnFileChangedByOperation(changed_file);
  }

  if (error != FILE_ERROR_OK || !*should_copy_on_server) {
    params->callback.Run(error);
    return;
  }

  if (params->parent_entry.resource_id().empty()) {
    // Parent entry may be being synced.
    const bool waiting = delegate_->WaitForSyncComplete(
        params->parent_entry.local_id(),
        base::Bind(&CopyOperation::CopyAfterParentSync,
                   weak_ptr_factory_.GetWeakPtr(), *params));
    if (!waiting)
      params->callback.Run(FILE_ERROR_NOT_FOUND);
  } else {
    CopyAfterGetParentResourceId(*params, &params->parent_entry, FILE_ERROR_OK);
  }
}

void CopyOperation::CopyAfterParentSync(const CopyParams& params,
                                        FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!params.callback.is_null());

  if (error != FILE_ERROR_OK) {
    params.callback.Run(error);
    return;
  }

  ResourceEntry* parent = new ResourceEntry;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&internal::ResourceMetadata::GetResourceEntryById,
                 base::Unretained(metadata_),
                 params.parent_entry.local_id(),
                 parent),
      base::Bind(&CopyOperation::CopyAfterGetParentResourceId,
                 weak_ptr_factory_.GetWeakPtr(),
                 params,
                 base::Owned(parent)));
}

void CopyOperation::CopyAfterGetParentResourceId(const CopyParams& params,
                                                 const ResourceEntry* parent,
                                                 FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!params.callback.is_null());

  if (error != FILE_ERROR_OK) {
    params.callback.Run(error);
    return;
  }

  base::FilePath new_title = params.dest_file_path.BaseName();
  if (params.src_entry.file_specific_info().is_hosted_document()) {
    // Drop the document extension, which should not be in the title.
    // TODO(yoshiki): Remove this code with crbug.com/223304.
    new_title = new_title.RemoveExtension();
  }

  base::Time last_modified =
      params.preserve_last_modified ?
      base::Time::FromInternalValue(
          params.src_entry.file_info().last_modified()) : base::Time();

  CopyResourceOnServer(
      params.src_entry.resource_id(), parent->resource_id(),
      new_title.AsUTF8Unsafe(), last_modified, params.callback);
}

void CopyOperation::TransferFileFromLocalToRemote(
    const base::FilePath& local_src_path,
    const base::FilePath& remote_dest_path,
    const FileOperationCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  std::string* gdoc_resource_id = new std::string;
  ResourceEntry* parent_entry = new ResourceEntry;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(
          &PrepareTransferFileFromLocalToRemote,
          metadata_, local_src_path, remote_dest_path,
          gdoc_resource_id, parent_entry),
      base::Bind(
          &CopyOperation::TransferFileFromLocalToRemoteAfterPrepare,
          weak_ptr_factory_.GetWeakPtr(),
          local_src_path, remote_dest_path, callback,
          base::Owned(gdoc_resource_id), base::Owned(parent_entry)));
}

void CopyOperation::TransferFileFromLocalToRemoteAfterPrepare(
    const base::FilePath& local_src_path,
    const base::FilePath& remote_dest_path,
    const FileOperationCallback& callback,
    std::string* gdoc_resource_id,
    ResourceEntry* parent_entry,
    FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  if (error != FILE_ERROR_OK) {
    callback.Run(error);
    return;
  }

  // For regular files, schedule the transfer.
  if (gdoc_resource_id->empty()) {
    ScheduleTransferRegularFile(local_src_path, remote_dest_path, callback);
    return;
  }

  // GDoc file may contain a resource ID in the old format.
  const std::string canonicalized_resource_id =
      util::CanonicalizeResourceId(*gdoc_resource_id);

  // Drop the document extension, which should not be in the title.
  // TODO(yoshiki): Remove this code with crbug.com/223304.
  const std::string new_title =
      remote_dest_path.BaseName().RemoveExtension().AsUTF8Unsafe();

  // This is uploading a JSON file representing a hosted document.
  TransferJsonGdocParams* params = new TransferJsonGdocParams(
      callback, canonicalized_resource_id, *parent_entry, new_title);
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&LocalWorkForTransferJsonGdocFile, metadata_, params),
      base::Bind(&CopyOperation::TransferJsonGdocFileAfterLocalWork,
                 weak_ptr_factory_.GetWeakPtr(), base::Owned(params)));
}

void CopyOperation::TransferJsonGdocFileAfterLocalWork(
    TransferJsonGdocParams* params,
    FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (error != FILE_ERROR_OK) {
    params->callback.Run(error);
    return;
  }

  switch (params->location_type) {
    // When |resource_id| is found in the local metadata and it has a specific
    // parent folder, we assume the user's intention is to copy the document and
    // thus perform the server-side copy operation.
    case HAS_PARENT:
      CopyResourceOnServer(params->resource_id,
                           params->parent_resource_id,
                           params->new_title,
                           base::Time(),
                           params->callback);
      break;
    // When |resource_id| has no parent, we just set the new destination folder
    // as the parent, for sharing the document between the original source.
    // This reparenting is already done in LocalWorkForTransferJsonGdocFile().
    case IS_ORPHAN: {
      DCHECK(!params->changed_path.empty());
      // Syncing for copy should be done in background, so pass the BACKGROUND
      // context. See: crbug.com/420278.
      delegate_->OnEntryUpdatedByOperation(ClientContext(BACKGROUND),
                                           params->local_id);

      FileChange changed_file;
      changed_file.Update(
          params->changed_path,
          FileChange::FILE_TYPE_FILE,  // This must be a hosted document.
          FileChange::CHANGE_TYPE_ADD_OR_UPDATE);
      delegate_->OnFileChangedByOperation(changed_file);
      params->callback.Run(error);
      break;
    }
    // When the |resource_id| is not in the local metadata, assume it to be a
    // document just now shared on the server but not synced locally.
    // Same as the IS_ORPHAN case, we want to deal the case by setting parent,
    // but this time we need to resort to server side operation.
    case NOT_IN_METADATA:
      scheduler_->UpdateResource(
          params->resource_id, params->parent_resource_id, params->new_title,
          base::Time(), base::Time(), google_apis::drive::Properties(),
          ClientContext(USER_INITIATED),
          base::Bind(&CopyOperation::UpdateAfterServerSideOperation,
                     weak_ptr_factory_.GetWeakPtr(), params->callback));
      break;
  }
}

void CopyOperation::CopyResourceOnServer(
    const std::string& resource_id,
    const std::string& parent_resource_id,
    const std::string& new_title,
    const base::Time& last_modified,
    const FileOperationCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  scheduler_->CopyResource(
      resource_id, parent_resource_id, new_title, last_modified,
      base::Bind(&CopyOperation::UpdateAfterServerSideOperation,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback));
}

void CopyOperation::UpdateAfterServerSideOperation(
    const FileOperationCallback& callback,
    google_apis::DriveApiErrorCode status,
    scoped_ptr<google_apis::FileResource> entry) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  FileError error = GDataToFileError(status);
  if (error != FILE_ERROR_OK) {
    callback.Run(error);
    return;
  }

  ResourceEntry* resource_entry = new ResourceEntry;

  // The copy on the server side is completed successfully. Update the local
  // metadata.
  base::FilePath* file_path = new base::FilePath;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&UpdateLocalStateForServerSideOperation,
                 metadata_,
                 base::Passed(&entry),
                 resource_entry,
                 file_path),
      base::Bind(&CopyOperation::UpdateAfterLocalStateUpdate,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback,
                 base::Owned(file_path),
                 base::Owned(resource_entry)));
}

void CopyOperation::UpdateAfterLocalStateUpdate(
    const FileOperationCallback& callback,
    base::FilePath* file_path,
    const ResourceEntry* entry,
    FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  if (error == FILE_ERROR_OK) {
    FileChange changed_file;
    changed_file.Update(*file_path, *entry,
                        FileChange::CHANGE_TYPE_ADD_OR_UPDATE);
    delegate_->OnFileChangedByOperation(changed_file);
  }
  callback.Run(error);
}

void CopyOperation::ScheduleTransferRegularFile(
    const base::FilePath& local_src_path,
    const base::FilePath& remote_dest_path,
    const FileOperationCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  create_file_operation_->CreateFile(
      remote_dest_path,
      false,  // Not exclusive (OK even if a file already exists).
      std::string(),  // no specific mime type; CreateFile should guess it.
      base::Bind(&CopyOperation::ScheduleTransferRegularFileAfterCreate,
                 weak_ptr_factory_.GetWeakPtr(),
                 local_src_path, remote_dest_path, callback));
}

void CopyOperation::ScheduleTransferRegularFileAfterCreate(
    const base::FilePath& local_src_path,
    const base::FilePath& remote_dest_path,
    const FileOperationCallback& callback,
    FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  if (error != FILE_ERROR_OK) {
    callback.Run(error);
    return;
  }

  std::string* local_id = new std::string;
  ResourceEntry* entry = new ResourceEntry;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&UpdateLocalStateForScheduleTransfer,
                 metadata_,
                 cache_,
                 local_src_path,
                 remote_dest_path,
                 entry,
                 local_id),
      base::Bind(
          &CopyOperation::ScheduleTransferRegularFileAfterUpdateLocalState,
          weak_ptr_factory_.GetWeakPtr(),
          callback,
          remote_dest_path,
          base::Owned(entry),
          base::Owned(local_id)));
}

void CopyOperation::ScheduleTransferRegularFileAfterUpdateLocalState(
    const FileOperationCallback& callback,
    const base::FilePath& remote_dest_path,
    const ResourceEntry* entry,
    std::string* local_id,
    FileError error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  if (error == FILE_ERROR_OK) {
    FileChange changed_file;
    changed_file.Update(remote_dest_path, *entry,
                        FileChange::CHANGE_TYPE_ADD_OR_UPDATE);
    delegate_->OnFileChangedByOperation(changed_file);
    // Syncing for copy should be done in background, so pass the BACKGROUND
    // context. See: crbug.com/420278.
    delegate_->OnEntryUpdatedByOperation(ClientContext(BACKGROUND), *local_id);
  }
  callback.Run(error);
}

}  // namespace file_system
}  // namespace drive
