// 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 "webkit/fileapi/isolated_file_util.h"

#include <string>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "webkit/blob/shareable_file_reference.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_url.h"
#include "webkit/fileapi/isolated_context.h"
#include "webkit/fileapi/native_file_util.h"

using base::PlatformFileError;
using base::PlatformFileInfo;

namespace fileapi {

typedef IsolatedContext::FileInfo FileInfo;

namespace {

// Simply enumerate each path from a given fileinfo set.
// Used to enumerate top-level paths of an isolated filesystem.
class SetFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator {
 public:
  explicit SetFileEnumerator(const std::vector<FileInfo>& files)
      : files_(files) {
    file_iter_ = files_.begin();
  }
  virtual ~SetFileEnumerator() {}

  // AbstractFileEnumerator overrides.
  virtual FilePath Next() OVERRIDE {
    if (file_iter_ == files_.end())
      return FilePath();
    FilePath platform_file = (file_iter_++)->path;
    NativeFileUtil::GetFileInfo(platform_file, &file_info_);
    return platform_file;
  }
  virtual int64 Size() OVERRIDE { return file_info_.size; }
  virtual bool IsDirectory() OVERRIDE { return file_info_.is_directory; }
  virtual base::Time LastModifiedTime() OVERRIDE {
    return file_info_.last_modified;
  }

 private:
  std::vector<FileInfo> files_;
  std::vector<FileInfo>::const_iterator file_iter_;
  base::PlatformFileInfo file_info_;
};

// Recursively enumerate each path from a given paths set.
class RecursiveSetFileEnumerator
    : public FileSystemFileUtil::AbstractFileEnumerator {
 public:
  RecursiveSetFileEnumerator(const std::vector<FileInfo>& files)
      : files_(files) {
    file_iter_ = files_.begin();
    current_enumerator_.reset(new SetFileEnumerator(files));
  }
  virtual ~RecursiveSetFileEnumerator() {}

  // AbstractFileEnumerator overrides.
  virtual FilePath Next() OVERRIDE;
  virtual int64 Size() OVERRIDE {
    DCHECK(current_enumerator_.get());
    return current_enumerator_->Size();
  }
  virtual bool IsDirectory() OVERRIDE {
    DCHECK(current_enumerator_.get());
    return current_enumerator_->IsDirectory();
  }
  virtual base::Time LastModifiedTime() OVERRIDE {
    DCHECK(current_enumerator_.get());
    return current_enumerator_->LastModifiedTime();
  }

 private:
  std::vector<FileInfo> files_;
  std::vector<FileInfo>::iterator file_iter_;
  base::PlatformFileInfo file_info_;
  scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> current_enumerator_;
};

FilePath RecursiveSetFileEnumerator::Next() {
  if (current_enumerator_.get()) {
    FilePath path = current_enumerator_->Next();
    if (!path.empty())
      return path;
  }

  // We reached the end.
  if (file_iter_ == files_.end())
    return FilePath();

  // Enumerates subdirectories of the next path.
  FileInfo& next_file = *file_iter_++;
  current_enumerator_.reset(
        NativeFileUtil::CreateFileEnumerator(
            next_file.path, true /* recursive */));
  DCHECK(current_enumerator_.get());
  return current_enumerator_->Next();
}

}  // namespace

//-------------------------------------------------------------------------

IsolatedFileUtil::IsolatedFileUtil() {}

PlatformFileError IsolatedFileUtil::GetLocalFilePath(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    FilePath* local_file_path) {
  DCHECK(local_file_path);
  if (url.path().empty()) {
    // Root direcory case, which should not be accessed.
    return base::PLATFORM_FILE_ERROR_ACCESS_DENIED;
  }
  *local_file_path = url.path();
  return base::PLATFORM_FILE_OK;
}

//-------------------------------------------------------------------------

DraggedFileUtil::DraggedFileUtil() {}

PlatformFileError DraggedFileUtil::GetFileInfo(
    FileSystemOperationContext* context,
    const FileSystemURL& url,
    PlatformFileInfo* file_info,
    FilePath* platform_path) {
  DCHECK(file_info);
  std::string filesystem_id;
  if (url.path().empty()) {
    // The root directory case.
    // For now we leave three time fields (modified/accessed/creation time)
    // NULL as it is not really clear what to be set for this virtual directory.
    // TODO(kinuko): Maybe we want to set the time when this filesystem is
    // created (i.e. when the files/directories are dropped).
    file_info->is_directory = true;
    file_info->is_symbolic_link = false;
    file_info->size = 0;
    return base::PLATFORM_FILE_OK;
  }
  base::PlatformFileError error =
      NativeFileUtil::GetFileInfo(url.path(), file_info);
  if (file_util::IsLink(url.path()) && !FilePath().IsParent(url.path())) {
    // Don't follow symlinks unless it's the one that are selected by the user.
    return base::PLATFORM_FILE_ERROR_NOT_FOUND;
  }
  if (error == base::PLATFORM_FILE_OK)
    *platform_path = url.path();
  return error;
}

FileSystemFileUtil::AbstractFileEnumerator*
DraggedFileUtil::CreateFileEnumerator(
    FileSystemOperationContext* context,
    const FileSystemURL& root,
    bool recursive) {
  if (!root.path().empty())
    return NativeFileUtil::CreateFileEnumerator(root.path(), recursive);

  // Root path case.
  std::vector<FileInfo> toplevels;
  IsolatedContext::GetInstance()->GetDraggedFileInfo(
      root.filesystem_id(), &toplevels);
  if (!recursive)
    return new SetFileEnumerator(toplevels);
  return new RecursiveSetFileEnumerator(toplevels);
}

bool DraggedFileUtil::PathExists(
    FileSystemOperationContext* context,
    const FileSystemURL& url) {
  if (url.path().empty()) {
    // The root directory case.
    return true;
  }
  return NativeFileUtil::PathExists(url.path());
}

bool DraggedFileUtil::DirectoryExists(
    FileSystemOperationContext* context,
    const FileSystemURL& url) {
  if (url.path().empty()) {
    // The root directory case.
    return true;
  }
  return NativeFileUtil::DirectoryExists(url.path());
}

bool DraggedFileUtil::IsDirectoryEmpty(
    FileSystemOperationContext* context,
    const FileSystemURL& url) {
  if (url.path().empty()) {
    // The root directory case.
    std::vector<FileInfo> toplevels;
    bool success = IsolatedContext::GetInstance()->GetDraggedFileInfo(
        url.filesystem_id(), &toplevels);
    DCHECK(success);
    return toplevels.empty();
  }
  return NativeFileUtil::IsDirectoryEmpty(url.path());
}

}  // namespace
