// Copyright (c) 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 "webkit/browser/fileapi/recursive_operation_delegate.h"

#include "base/bind.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"

namespace fileapi {

namespace {
// Don't start too many inflight operations.
const int kMaxInflightOperations = 5;
}

RecursiveOperationDelegate::RecursiveOperationDelegate(
    FileSystemContext* file_system_context)
    : file_system_context_(file_system_context),
      inflight_operations_(0),
      canceled_(false) {
}

RecursiveOperationDelegate::~RecursiveOperationDelegate() {
}

void RecursiveOperationDelegate::Cancel() {
  canceled_ = true;
  OnCancel();
}

void RecursiveOperationDelegate::StartRecursiveOperation(
    const FileSystemURL& root,
    const StatusCallback& callback) {
  DCHECK(pending_directory_stack_.empty());
  DCHECK(pending_files_.empty());
  DCHECK_EQ(0, inflight_operations_);

  callback_ = callback;
  ++inflight_operations_;
  ProcessFile(
      root,
      base::Bind(&RecursiveOperationDelegate::DidTryProcessFile,
                 AsWeakPtr(), root));
}

FileSystemOperationRunner* RecursiveOperationDelegate::operation_runner() {
  return file_system_context_->operation_runner();
}

void RecursiveOperationDelegate::OnCancel() {
}

void RecursiveOperationDelegate::DidTryProcessFile(
    const FileSystemURL& root,
    base::PlatformFileError error) {
  DCHECK(pending_directory_stack_.empty());
  DCHECK(pending_files_.empty());
  DCHECK_EQ(1, inflight_operations_);

  --inflight_operations_;
  if (canceled_ || error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) {
    Done(error);
    return;
  }

  pending_directory_stack_.push(std::queue<FileSystemURL>());
  pending_directory_stack_.top().push(root);
  ProcessNextDirectory();
}

void RecursiveOperationDelegate::ProcessNextDirectory() {
  DCHECK(pending_files_.empty());
  DCHECK(!pending_directory_stack_.empty());
  DCHECK(!pending_directory_stack_.top().empty());
  DCHECK_EQ(0, inflight_operations_);

  const FileSystemURL& url = pending_directory_stack_.top().front();

  ++inflight_operations_;
  ProcessDirectory(
      url,
      base::Bind(
          &RecursiveOperationDelegate::DidProcessDirectory, AsWeakPtr()));
}

void RecursiveOperationDelegate::DidProcessDirectory(
    base::PlatformFileError error) {
  DCHECK(pending_files_.empty());
  DCHECK(!pending_directory_stack_.empty());
  DCHECK(!pending_directory_stack_.top().empty());
  DCHECK_EQ(1, inflight_operations_);

  --inflight_operations_;
  if (canceled_ || error != base::PLATFORM_FILE_OK) {
    Done(error);
    return;
  }

  const FileSystemURL& parent = pending_directory_stack_.top().front();
  pending_directory_stack_.push(std::queue<FileSystemURL>());
  operation_runner()->ReadDirectory(
      parent,
      base::Bind(&RecursiveOperationDelegate::DidReadDirectory,
                 AsWeakPtr(), parent));
}

void RecursiveOperationDelegate::DidReadDirectory(
    const FileSystemURL& parent,
    base::PlatformFileError error,
    const FileEntryList& entries,
    bool has_more) {
  DCHECK(pending_files_.empty());
  DCHECK(!pending_directory_stack_.empty());
  DCHECK_EQ(0, inflight_operations_);

  if (canceled_ || error != base::PLATFORM_FILE_OK) {
    Done(error);
    return;
  }

  for (size_t i = 0; i < entries.size(); i++) {
    FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
        parent.origin(),
        parent.mount_type(),
        parent.virtual_path().Append(entries[i].name));
    if (entries[i].is_directory)
      pending_directory_stack_.top().push(url);
    else
      pending_files_.push(url);
  }

  // Wait for next entries.
  if (has_more)
    return;

  ProcessPendingFiles();
}

void RecursiveOperationDelegate::ProcessPendingFiles() {
  DCHECK(!pending_directory_stack_.empty());

  if ((pending_files_.empty() || canceled_) && inflight_operations_ == 0) {
    ProcessSubDirectory();
    return;
  }

  // Do not post any new tasks.
  if (canceled_)
    return;

  // Run ProcessFile in parallel (upto kMaxInflightOperations).
  scoped_refptr<base::MessageLoopProxy> current_message_loop =
      base::MessageLoopProxy::current();
  while (!pending_files_.empty() &&
         inflight_operations_ < kMaxInflightOperations) {
    ++inflight_operations_;
    current_message_loop->PostTask(
        FROM_HERE,
        base::Bind(&RecursiveOperationDelegate::ProcessFile,
                   AsWeakPtr(), pending_files_.front(),
                   base::Bind(&RecursiveOperationDelegate::DidProcessFile,
                              AsWeakPtr())));
    pending_files_.pop();
  }
}

void RecursiveOperationDelegate::DidProcessFile(
    base::PlatformFileError error) {
  --inflight_operations_;
  if (error != base::PLATFORM_FILE_OK) {
    // If an error occurs, invoke Done immediately (even if there remain
    // running operations). It is because in the callback, this instance is
    // deleted.
    Done(error);
    return;
  }

  ProcessPendingFiles();
}

void RecursiveOperationDelegate::ProcessSubDirectory() {
  DCHECK(pending_files_.empty());
  DCHECK(!pending_directory_stack_.empty());
  DCHECK_EQ(0, inflight_operations_);

  if (canceled_) {
    Done(base::PLATFORM_FILE_ERROR_ABORT);
    return;
  }

  if (!pending_directory_stack_.top().empty()) {
    // There remain some sub directories. Process them first.
    ProcessNextDirectory();
    return;
  }

  // All subdirectories are processed.
  pending_directory_stack_.pop();
  if (pending_directory_stack_.empty()) {
    // All files/directories are processed.
    Done(base::PLATFORM_FILE_OK);
    return;
  }

  DCHECK(!pending_directory_stack_.top().empty());
  ++inflight_operations_;
  PostProcessDirectory(
      pending_directory_stack_.top().front(),
      base::Bind(&RecursiveOperationDelegate::DidPostProcessDirectory,
                 AsWeakPtr()));
}

void RecursiveOperationDelegate::DidPostProcessDirectory(
    base::PlatformFileError error) {
  DCHECK(pending_files_.empty());
  DCHECK(!pending_directory_stack_.empty());
  DCHECK(!pending_directory_stack_.top().empty());
  DCHECK_EQ(1, inflight_operations_);

  --inflight_operations_;
  pending_directory_stack_.top().pop();
  if (canceled_ || error != base::PLATFORM_FILE_OK) {
    Done(error);
    return;
  }

  ProcessSubDirectory();
}

void RecursiveOperationDelegate::Done(base::PlatformFileError error) {
  if (canceled_ && error == base::PLATFORM_FILE_OK) {
    callback_.Run(base::PLATFORM_FILE_ERROR_ABORT);
  } else {
    callback_.Run(error);
  }
}

}  // namespace fileapi
