// Copyright 2013 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 "chrome/browser/chromeos/drive/file_system/download_operation.h"

#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/task_runner_util.h"
#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/file_cache.h"
#include "chrome/browser/chromeos/drive/file_errors.h"
#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/drive/job_scheduler.h"
#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
#include "chrome/browser/chromeos/drive/resource_metadata.h"
#include "chrome/browser/google_apis/gdata_errorcode.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace drive {
namespace file_system {
namespace {

// If the resource is a hosted document, creates a JSON file representing the
// resource locally, and returns FILE_ERROR_OK with |cache_file_path| storing
// the path to the JSON file.
// If the resource is a regular file and its local cache is available,
// returns FILE_ERROR_OK with |cache_file_path| storing the path to the
// cache file.
// If the resource is a regular file but its local cache is NOT available,
// returns FILE_ERROR_OK, but |cache_file_path| is kept empty.
// Otherwise returns error code.
FileError CheckPreConditionForEnsureFileDownloaded(
    internal::ResourceMetadata* metadata,
    internal::FileCache* cache,
    const base::FilePath& temporary_file_directory,
    const std::string& local_id,
    ResourceEntry* entry,
    base::FilePath* cache_file_path) {
  DCHECK(metadata);
  DCHECK(cache);
  DCHECK(cache_file_path);

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

  if (entry->file_info().is_directory())
    return FILE_ERROR_NOT_A_FILE;

  // The file's entry should have its file specific info.
  DCHECK(entry->has_file_specific_info());

  // For a hosted document, we create a special JSON file to represent the
  // document instead of fetching the document content in one of the exported
  // formats. The JSON file contains the edit URL and resource ID of the
  // document.
  if (entry->file_specific_info().is_hosted_document()) {
    base::FilePath gdoc_file_path;
    base::PlatformFileInfo file_info;
    if (!file_util::CreateTemporaryFileInDir(temporary_file_directory,
                                             &gdoc_file_path) ||
        !util::CreateGDocFile(gdoc_file_path,
                              GURL(entry->file_specific_info().alternate_url()),
                              entry->resource_id()) ||
        !file_util::GetFileInfo(gdoc_file_path, &file_info))
      return FILE_ERROR_FAILED;

    *cache_file_path = gdoc_file_path;
    SetPlatformFileInfoToResourceEntry(file_info, entry);
    return FILE_ERROR_OK;
  }

  // Leave |cache_file_path| empty when no cache entry is found.
  FileCacheEntry cache_entry;
  if (!cache->GetCacheEntry(local_id, &cache_entry))
    return FILE_ERROR_OK;

  // Leave |cache_file_path| empty when the stored file is obsolete and has no
  // local modification.
  if (!cache_entry.is_dirty() &&
      entry->file_specific_info().md5() != cache_entry.md5())
    return FILE_ERROR_OK;

  // Fill |cache_file_path| with the path to the cached file.
  error = cache->GetFile(local_id, cache_file_path);
  if (error != FILE_ERROR_OK)
    return error;

  // If the cache file is dirty, the modified file info needs to be stored in
  // |entry|.
  // TODO(kinaba): crbug.com/246469. The logic below is a duplicate of that in
  // drive::FileSystem::CheckLocalModificationAndRun. We should merge them once
  // the drive::FS side is also converted to run fully on blocking pool.
  if (cache_entry.is_dirty()) {
    base::PlatformFileInfo file_info;
    if (file_util::GetFileInfo(*cache_file_path, &file_info))
      SetPlatformFileInfoToResourceEntry(file_info, entry);
  }

  return FILE_ERROR_OK;
}

// Calls CheckPreConditionForEnsureFileDownloaded() with the entry specified by
// the given ID. Also fills |drive_file_path| with the path of the entry.
FileError CheckPreConditionForEnsureFileDownloadedByLocalId(
    internal::ResourceMetadata* metadata,
    internal::FileCache* cache,
    const std::string& local_id,
    const base::FilePath& temporary_file_directory,
    base::FilePath* drive_file_path,
    base::FilePath* cache_file_path,
    ResourceEntry* entry) {
  *drive_file_path = metadata->GetFilePath(local_id);
  return CheckPreConditionForEnsureFileDownloaded(
      metadata, cache, temporary_file_directory, local_id, entry,
      cache_file_path);
}

// Calls CheckPreConditionForEnsureFileDownloaded() with the entry specified by
// the given file path.
FileError CheckPreConditionForEnsureFileDownloadedByPath(
    internal::ResourceMetadata* metadata,
    internal::FileCache* cache,
    const base::FilePath& file_path,
    const base::FilePath& temporary_file_directory,
    std::string* local_id,
    base::FilePath* cache_file_path,
    ResourceEntry* entry) {
  FileError error = metadata->GetIdByPath(file_path, local_id);
  if (error != FILE_ERROR_OK)
    return error;
  return CheckPreConditionForEnsureFileDownloaded(
      metadata, cache, temporary_file_directory, *local_id, entry,
      cache_file_path);
}

// Creates a file with unique name in |dir| and stores the path to |temp_file|.
// Additionally, sets the permission of the file to allow read access from
// others and group member users (i.e, "-rw-r--r--").
// We need this wrapper because Drive cache files may be read from other
// processes (e.g., cros_disks for mounting zip files).
bool CreateTemporaryReadableFileInDir(const base::FilePath& dir,
                                      base::FilePath* temp_file) {
  if (!file_util::CreateTemporaryFileInDir(dir, temp_file))
    return false;
  return file_util::SetPosixFilePermissions(
      *temp_file,
      file_util::FILE_PERMISSION_READ_BY_USER |
      file_util::FILE_PERMISSION_WRITE_BY_USER |
      file_util::FILE_PERMISSION_READ_BY_GROUP |
      file_util::FILE_PERMISSION_READ_BY_OTHERS);
}

// Prepares for downloading the file. Allocates the enough space for the file
// in the cache.
// If succeeded, returns FILE_ERROR_OK with |temp_download_file| storing the
// path to the file in the cache.
FileError PrepareForDownloadFile(internal::FileCache* cache,
                                 int64 expected_file_size,
                                 const base::FilePath& temporary_file_directory,
                                 base::FilePath* temp_download_file) {
  DCHECK(cache);
  DCHECK(temp_download_file);

  // Ensure enough space in the cache.
  if (!cache->FreeDiskSpaceIfNeededFor(expected_file_size))
    return FILE_ERROR_NO_LOCAL_SPACE;

  // Create the temporary file which will store the downloaded content.
  return CreateTemporaryReadableFileInDir(
      temporary_file_directory,
      temp_download_file) ? FILE_ERROR_OK : FILE_ERROR_FAILED;
}

// Stores the downloaded file at |downloaded_file_path| into |cache|.
// If succeeded, returns FILE_ERROR_OK with |cache_file_path| storing the
// path to the cache file.
// If failed, returns an error code with deleting |downloaded_file_path|.
FileError UpdateLocalStateForDownloadFile(
    internal::FileCache* cache,
    const std::string& local_id,
    const std::string& md5,
    google_apis::GDataErrorCode gdata_error,
    const base::FilePath& downloaded_file_path,
    base::FilePath* cache_file_path) {
  DCHECK(cache);

  FileError error = GDataToFileError(gdata_error);
  if (error != FILE_ERROR_OK) {
    base::DeleteFile(downloaded_file_path, false /* recursive */);
    return error;
  }

  // Here the download is completed successfully, so store it into the cache.
  error = cache->Store(local_id, md5, downloaded_file_path,
                       internal::FileCache::FILE_OPERATION_MOVE);
  if (error != FILE_ERROR_OK) {
    base::DeleteFile(downloaded_file_path, false /* recursive */);
    return error;
  }

  return cache->GetFile(local_id, cache_file_path);
}

}  // namespace

class DownloadOperation::DownloadParams {
 public:
  DownloadParams(
      const GetFileContentInitializedCallback initialized_callback,
      const google_apis::GetContentCallback get_content_callback,
      const GetFileCallback completion_callback,
      scoped_ptr<ResourceEntry> entry)
      : initialized_callback_(initialized_callback),
        get_content_callback_(get_content_callback),
        completion_callback_(completion_callback),
        entry_(entry.Pass()) {
    DCHECK(!completion_callback_.is_null());
    DCHECK(entry_);
  }

  void OnCacheFileFound(const base::FilePath& cache_file_path) const {
    if (initialized_callback_.is_null())
      return;

    DCHECK(entry_);
    initialized_callback_.Run(
        FILE_ERROR_OK, make_scoped_ptr(new ResourceEntry(*entry_)),
        cache_file_path, base::Closure());
  }

  void OnStartDownloading(const base::Closure& cancel_download_closure) const {
    if (initialized_callback_.is_null()) {
      return;
    }

    DCHECK(entry_);
    initialized_callback_.Run(
        FILE_ERROR_OK, make_scoped_ptr(new ResourceEntry(*entry_)),
        base::FilePath(), cancel_download_closure);
  }

  void OnError(FileError error) const {
    completion_callback_.Run(
        error, base::FilePath(), scoped_ptr<ResourceEntry>());
  }

  void OnComplete(const base::FilePath& cache_file_path) {
    completion_callback_.Run(FILE_ERROR_OK, cache_file_path, entry_.Pass());
  }

  const google_apis::GetContentCallback& get_content_callback() const {
    return get_content_callback_;
  }

  const ResourceEntry& entry() const { return *entry_; }

 private:
  const GetFileContentInitializedCallback initialized_callback_;
  const google_apis::GetContentCallback get_content_callback_;
  const GetFileCallback completion_callback_;

  scoped_ptr<ResourceEntry> entry_;

  DISALLOW_COPY_AND_ASSIGN(DownloadParams);
};

DownloadOperation::DownloadOperation(
    base::SequencedTaskRunner* blocking_task_runner,
    OperationObserver* observer,
    JobScheduler* scheduler,
    internal::ResourceMetadata* metadata,
    internal::FileCache* cache,
    const base::FilePath& temporary_file_directory)
    : blocking_task_runner_(blocking_task_runner),
      observer_(observer),
      scheduler_(scheduler),
      metadata_(metadata),
      cache_(cache),
      temporary_file_directory_(temporary_file_directory),
      weak_ptr_factory_(this) {
}

DownloadOperation::~DownloadOperation() {
}

void DownloadOperation::EnsureFileDownloadedByLocalId(
    const std::string& local_id,
    const ClientContext& context,
    const GetFileContentInitializedCallback& initialized_callback,
    const google_apis::GetContentCallback& get_content_callback,
    const GetFileCallback& completion_callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!completion_callback.is_null());

  base::FilePath* drive_file_path = new base::FilePath;
  base::FilePath* cache_file_path = new base::FilePath;
  ResourceEntry* entry = new ResourceEntry;
  scoped_ptr<DownloadParams> params(new DownloadParams(
      initialized_callback, get_content_callback, completion_callback,
      make_scoped_ptr(entry)));
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&CheckPreConditionForEnsureFileDownloadedByLocalId,
                 base::Unretained(metadata_),
                 base::Unretained(cache_),
                 local_id,
                 temporary_file_directory_,
                 drive_file_path,
                 cache_file_path,
                 entry),
      base::Bind(&DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&params),
                 context,
                 base::Owned(new std::string(local_id)),
                 base::Owned(drive_file_path),
                 base::Owned(cache_file_path)));
}

void DownloadOperation::EnsureFileDownloadedByPath(
    const base::FilePath& file_path,
    const ClientContext& context,
    const GetFileContentInitializedCallback& initialized_callback,
    const google_apis::GetContentCallback& get_content_callback,
    const GetFileCallback& completion_callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!completion_callback.is_null());

  std::string* local_id = new std::string;
  base::FilePath* drive_file_path = new base::FilePath(file_path);
  base::FilePath* cache_file_path = new base::FilePath;
  ResourceEntry* entry = new ResourceEntry;
  scoped_ptr<DownloadParams> params(new DownloadParams(
      initialized_callback, get_content_callback, completion_callback,
      make_scoped_ptr(entry)));
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&CheckPreConditionForEnsureFileDownloadedByPath,
                 base::Unretained(metadata_),
                 base::Unretained(cache_),
                 file_path,
                 temporary_file_directory_,
                 local_id,
                 cache_file_path,
                 entry),
      base::Bind(&DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&params),
                 context,
                 base::Owned(local_id),
                 base::Owned(drive_file_path),
                 base::Owned(cache_file_path)));
}

void DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition(
    scoped_ptr<DownloadParams> params,
    const ClientContext& context,
    std::string* local_id,
    base::FilePath* drive_file_path,
    base::FilePath* cache_file_path,
    FileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(params);
  DCHECK(local_id);
  DCHECK(drive_file_path);
  DCHECK(cache_file_path);

  if (error != FILE_ERROR_OK) {
    // During precondition check, an error is found.
    params->OnError(error);
    return;
  }

  if (!cache_file_path->empty()) {
    // The cache file is found.
    params->OnCacheFileFound(*cache_file_path);
    params->OnComplete(*cache_file_path);
    return;
  }

  // If cache file is not found, try to download the file from the server
  // instead. Check if we have enough space, based on the expected file size.
  // - if we don't have enough space, try to free up the disk space
  // - if we still don't have enough space, return "no space" error
  // - if we have enough space, start downloading the file from the server
  int64 size = params->entry().file_info().size();
  base::FilePath* temp_download_file_path = new base::FilePath;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&PrepareForDownloadFile,
                 base::Unretained(cache_),
                 size,
                 temporary_file_directory_,
                 temp_download_file_path),
      base::Bind(
          &DownloadOperation::EnsureFileDownloadedAfterPrepareForDownloadFile,
          weak_ptr_factory_.GetWeakPtr(),
          base::Passed(&params),
          context,
          *local_id,
          *drive_file_path,
          base::Owned(temp_download_file_path)));
}

void DownloadOperation::EnsureFileDownloadedAfterPrepareForDownloadFile(
    scoped_ptr<DownloadParams> params,
    const ClientContext& context,
    const std::string& local_id,
    const base::FilePath& drive_file_path,
    base::FilePath* temp_download_file_path,
    FileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(params);
  DCHECK(temp_download_file_path);

  if (error != FILE_ERROR_OK) {
    params->OnError(error);
    return;
  }

  DownloadParams* params_ptr = params.get();
  JobID id = scheduler_->DownloadFile(
      drive_file_path,
      params_ptr->entry().file_info().size(),
      *temp_download_file_path,
      params_ptr->entry().resource_id(),
      context,
      base::Bind(&DownloadOperation::EnsureFileDownloadedAfterDownloadFile,
                 weak_ptr_factory_.GetWeakPtr(),
                 drive_file_path,
                 local_id,
                 base::Passed(&params)),
      params_ptr->get_content_callback());

  // Notify via |initialized_callback| if necessary.
  params_ptr->OnStartDownloading(
      base::Bind(&DownloadOperation::CancelJob,
                 weak_ptr_factory_.GetWeakPtr(), id));
}

void DownloadOperation::EnsureFileDownloadedAfterDownloadFile(
    const base::FilePath& drive_file_path,
    const std::string& local_id,
    scoped_ptr<DownloadParams> params,
    google_apis::GDataErrorCode gdata_error,
    const base::FilePath& downloaded_file_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  const std::string& md5 = params->entry().file_specific_info().md5();
  base::FilePath* cache_file_path = new base::FilePath;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&UpdateLocalStateForDownloadFile,
                 base::Unretained(cache_),
                 local_id,
                 md5,
                 gdata_error,
                 downloaded_file_path,
                 cache_file_path),
      base::Bind(&DownloadOperation::EnsureFileDownloadedAfterUpdateLocalState,
                 weak_ptr_factory_.GetWeakPtr(),
                 drive_file_path,
                 base::Passed(&params),
                 base::Owned(cache_file_path)));
}

void DownloadOperation::EnsureFileDownloadedAfterUpdateLocalState(
    const base::FilePath& file_path,
    scoped_ptr<DownloadParams> params,
    base::FilePath* cache_file_path,
    FileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (error != FILE_ERROR_OK) {
    params->OnError(error);
    return;
  }

  // Storing to cache changes the "offline available" status, hence notify.
  observer_->OnDirectoryChangedByOperation(file_path.DirName());
  params->OnComplete(*cache_file_path);
}

void DownloadOperation::CancelJob(JobID job_id) {
  scheduler_->CancelJob(job_id);
}

}  // namespace file_system
}  // namespace drive
