// 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/extensions/file_manager/private_api_tasks.h"

#include "chrome/browser/chromeos/drive/drive_app_registry.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/storage_partition.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_url.h"

using content::BrowserContext;
using extensions::app_file_handler_util::FindFileHandlersForFiles;
using extensions::app_file_handler_util::PathAndMimeTypeSet;
using extensions::Extension;
using fileapi::FileSystemURL;

namespace file_manager {
namespace {

// Error messages.
const char kInvalidFileUrl[] = "Invalid file URL";

// Default icon path for drive docs.
const char kDefaultIcon[] = "images/filetype_generic.png";

// Logs the default task for debugging.
void LogDefaultTask(const std::set<std::string>& mime_types,
                    const std::set<std::string>& suffixes,
                    const std::string& task_id) {
  if (!mime_types.empty()) {
    std::string mime_types_str;
    for (std::set<std::string>::const_iterator iter = mime_types.begin();
         iter != mime_types.end(); ++iter) {
      if (iter == mime_types.begin()) {
        mime_types_str = *iter;
      } else {
        mime_types_str += ", " + *iter;
      }
    }
    VLOG(1) << "Associating task " << task_id
            << " with the following MIME types: ";
    VLOG(1) << "  " << mime_types_str;
  }

  if (!suffixes.empty()) {
    std::string suffixes_str;
    for (std::set<std::string>::const_iterator iter = suffixes.begin();
         iter != suffixes.end(); ++iter) {
      if (iter == suffixes.begin()) {
        suffixes_str = *iter;
      } else {
        suffixes_str += ", " + *iter;
      }
    }
    VLOG(1) << "Associating task " << task_id
            << " with the following suffixes: ";
    VLOG(1) << "  " << suffixes_str;
  }
}

// Returns a task id for the web app with |app_id|.
std::string MakeWebAppTaskId(const std::string& app_id) {
  // TODO(gspencer): For now, the action id is always "open-with", but we
  // could add any actions that the drive app supports.
  return file_tasks::MakeTaskID(
      app_id, file_tasks::kTaskDrive, "open-with");
}

// Gets the mime types for the given file paths.
void GetMimeTypesForFileURLs(const std::vector<base::FilePath>& file_paths,
                             PathAndMimeTypeSet* files) {
  for (std::vector<base::FilePath>::const_iterator iter = file_paths.begin();
       iter != file_paths.end(); ++iter) {
    files->insert(
        std::make_pair(*iter, util::GetMimeTypeForPath(*iter)));
  }
}

// Make a set of unique filename suffixes out of the list of file URLs.
std::set<std::string> GetUniqueSuffixes(base::ListValue* file_url_list,
                                        fileapi::FileSystemContext* context) {
  std::set<std::string> suffixes;
  for (size_t i = 0; i < file_url_list->GetSize(); ++i) {
    std::string url_str;
    if (!file_url_list->GetString(i, &url_str))
      return std::set<std::string>();
    FileSystemURL url = context->CrackURL(GURL(url_str));
    if (!url.is_valid() || url.path().empty())
      return std::set<std::string>();
    // We'll skip empty suffixes.
    if (!url.path().Extension().empty())
      suffixes.insert(url.path().Extension());
  }
  return suffixes;
}

// Make a set of unique MIME types out of the list of MIME types.
std::set<std::string> GetUniqueMimeTypes(base::ListValue* mime_type_list) {
  std::set<std::string> mime_types;
  for (size_t i = 0; i < mime_type_list->GetSize(); ++i) {
    std::string mime_type;
    if (!mime_type_list->GetString(i, &mime_type))
      return std::set<std::string>();
    // We'll skip empty MIME types.
    if (!mime_type.empty())
      mime_types.insert(mime_type);
  }
  return mime_types;
}

}  // namespace

ExecuteTaskFunction::ExecuteTaskFunction() {
}

ExecuteTaskFunction::~ExecuteTaskFunction() {
}

bool ExecuteTaskFunction::RunImpl() {
  // First param is task id that was to the extension with getFileTasks call.
  std::string task_id;
  if (!args_->GetString(0, &task_id) || !task_id.size())
    return false;

  // TODO(kaznacheev): Crack the task_id here, store it in the Executor
  // and avoid passing it around.

  // The second param is the list of files that need to be executed with this
  // task.
  ListValue* files_list = NULL;
  if (!args_->GetList(1, &files_list))
    return false;

  std::string extension_id;
  std::string task_type;
  std::string action_id;
  if (!file_tasks::CrackTaskID(
          task_id, &extension_id, &task_type, &action_id)) {
    LOG(WARNING) << "Invalid task " << task_id;
    return false;
  }

  if (!files_list->GetSize())
    return true;

  content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
  scoped_refptr<fileapi::FileSystemContext> file_system_context =
      BrowserContext::GetStoragePartition(profile(), site_instance)->
      GetFileSystemContext();

  std::vector<FileSystemURL> file_urls;
  for (size_t i = 0; i < files_list->GetSize(); i++) {
    std::string file_url_str;
    if (!files_list->GetString(i, &file_url_str)) {
      error_ = kInvalidFileUrl;
      return false;
    }
    FileSystemURL url = file_system_context->CrackURL(GURL(file_url_str));
    if (!chromeos::FileSystemBackend::CanHandleURL(url)) {
      error_ = kInvalidFileUrl;
      return false;
    }
    file_urls.push_back(url);
  }

  int32 tab_id = util::GetTabId(dispatcher());
  return file_tasks::ExecuteFileTask(
      profile(),
      source_url(),
      extension_->id(),
      tab_id,
      extension_id,
      task_type,
      action_id,
      file_urls,
      base::Bind(&ExecuteTaskFunction::OnTaskExecuted, this));
}

void ExecuteTaskFunction::OnTaskExecuted(bool success) {
  SetResult(new base::FundamentalValue(success));
  SendResponse(true);
}

struct GetFileTasksFunction::FileInfo {
  GURL file_url;
  base::FilePath file_path;
  std::string mime_type;
};

struct GetFileTasksFunction::TaskInfo {
  TaskInfo(const string16& app_name, const GURL& icon_url)
      : app_name(app_name), icon_url(icon_url) {
  }

  string16 app_name;
  GURL icon_url;
};

GetFileTasksFunction::GetFileTasksFunction() {
}

GetFileTasksFunction::~GetFileTasksFunction() {
}

// static
void GetFileTasksFunction::GetAvailableDriveTasks(
    drive::DriveAppRegistry* registry,
    const FileInfoList& file_info_list,
    TaskInfoMap* task_info_map) {
  DCHECK(registry);
  DCHECK(task_info_map);
  DCHECK(task_info_map->empty());

  bool is_first = true;
  for (size_t i = 0; i < file_info_list.size(); ++i) {
    const FileInfo& file_info = file_info_list[i];
    if (file_info.file_path.empty())
      continue;

    ScopedVector<drive::DriveAppInfo> app_info_list;
    registry->GetAppsForFile(
        file_info.file_path, file_info.mime_type, &app_info_list);

    if (is_first) {
      // For the first file, we store all the info.
      for (size_t j = 0; j < app_info_list.size(); ++j) {
        const drive::DriveAppInfo& app_info = *app_info_list[j];
        GURL icon_url = util::FindPreferredIcon(app_info.app_icons,
                                                util::kPreferredIconSize);
        task_info_map->insert(std::pair<std::string, TaskInfo>(
            MakeWebAppTaskId(app_info.app_id),
            TaskInfo(app_info.app_name, icon_url)));
      }
    } else {
      // For remaining files, take the intersection with the current result,
      // based on the task id.
      std::set<std::string> task_id_set;
      for (size_t j = 0; j < app_info_list.size(); ++j) {
        task_id_set.insert(MakeWebAppTaskId(app_info_list[j]->app_id));
      }
      for (TaskInfoMap::iterator iter = task_info_map->begin();
           iter != task_info_map->end(); ) {
        if (task_id_set.find(iter->first) == task_id_set.end()) {
          task_info_map->erase(iter++);
        } else {
          ++iter;
        }
      }
    }

    is_first = false;
  }
}

void GetFileTasksFunction::FindDefaultDriveTasks(
    const FileInfoList& file_info_list,
    const TaskInfoMap& task_info_map,
    std::set<std::string>* default_tasks) {
  DCHECK(default_tasks);

  for (size_t i = 0; i < file_info_list.size(); ++i) {
    const FileInfo& file_info = file_info_list[i];
    std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
        profile_, file_info.mime_type, file_info.file_path.Extension());
    if (task_info_map.find(task_id) != task_info_map.end())
      default_tasks->insert(task_id);
  }
}

// static
void GetFileTasksFunction::CreateDriveTasks(
    const TaskInfoMap& task_info_map,
    const std::set<std::string>& default_tasks,
    ListValue* result_list,
    bool* default_already_set) {
  DCHECK(result_list);
  DCHECK(default_already_set);

  for (TaskInfoMap::const_iterator iter = task_info_map.begin();
       iter != task_info_map.end(); ++iter) {
    DictionaryValue* task = new DictionaryValue;
    task->SetString("taskId", iter->first);
    task->SetString("title", iter->second.app_name);

    const GURL& icon_url = iter->second.icon_url;
    if (!icon_url.is_empty())
      task->SetString("iconUrl", icon_url.spec());

    task->SetBoolean("driveApp", true);

    // Once we set a default app, we don't want to set any more.
    if (!(*default_already_set) &&
        default_tasks.find(iter->first) != default_tasks.end()) {
      task->SetBoolean("isDefault", true);
      *default_already_set = true;
    } else {
      task->SetBoolean("isDefault", false);
    }
    result_list->Append(task);
  }
}

// Find special tasks here for Drive (Blox) apps. Iterate through matching drive
// apps and add them, with generated task ids. Extension ids will be the app_ids
// from drive. We'll know that they are drive apps because the extension id will
// begin with kDriveTaskExtensionPrefix.
bool GetFileTasksFunction::FindDriveAppTasks(
    const FileInfoList& file_info_list,
    ListValue* result_list,
    bool* default_already_set) {
  DCHECK(result_list);
  DCHECK(default_already_set);

  if (file_info_list.empty())
    return true;

  drive::DriveIntegrationService* integration_service =
      drive::DriveIntegrationServiceFactory::GetForProfile(profile_);
  // |integration_service| is NULL if Drive is disabled. We return true in this
  // case because there might be other extension tasks, even if we don't have
  // any to add.
  if (!integration_service || !integration_service->drive_app_registry())
    return true;

  drive::DriveAppRegistry* registry =
      integration_service->drive_app_registry();
  DCHECK(registry);

  // Map of task_id to TaskInfo of available tasks.
  TaskInfoMap task_info_map;
  GetAvailableDriveTasks(registry, file_info_list, &task_info_map);
  std::set<std::string> default_tasks;
  FindDefaultDriveTasks(file_info_list, task_info_map, &default_tasks);
  CreateDriveTasks(
      task_info_map, default_tasks, result_list, default_already_set);
  return true;
}

bool GetFileTasksFunction::FindAppTasks(
    const std::vector<base::FilePath>& file_paths,
    ListValue* result_list,
    bool* default_already_set) {
  DCHECK(!file_paths.empty());
  ExtensionService* service = profile_->GetExtensionService();
  if (!service)
    return false;

  PathAndMimeTypeSet files;
  GetMimeTypesForFileURLs(file_paths, &files);
  std::set<std::string> default_tasks;
  for (PathAndMimeTypeSet::iterator it = files.begin(); it != files.end();
       ++it) {
    default_tasks.insert(file_tasks::GetDefaultTaskIdFromPrefs(
        profile_, it->second, it->first.Extension()));
  }

  for (ExtensionSet::const_iterator iter = service->extensions()->begin();
       iter != service->extensions()->end();
       ++iter) {
    const Extension* extension = iter->get();

    // We don't support using hosted apps to open files.
    if (!extension->is_platform_app())
      continue;

    if (profile_->IsOffTheRecord() &&
        !service->IsIncognitoEnabled(extension->id()))
      continue;

    typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList;
    FileHandlerList file_handlers = FindFileHandlersForFiles(*extension, files);
    if (file_handlers.empty())
      continue;

    for (FileHandlerList::iterator i = file_handlers.begin();
         i != file_handlers.end(); ++i) {
      DictionaryValue* task = new DictionaryValue;
      std::string task_id = file_tasks::MakeTaskID(
          extension->id(), file_tasks::kTaskApp, (*i)->id);
      task->SetString("taskId", task_id);
      task->SetString("title", (*i)->title);
      if (!(*default_already_set) && ContainsKey(default_tasks, task_id)) {
        task->SetBoolean("isDefault", true);
        *default_already_set = true;
      } else {
        task->SetBoolean("isDefault", false);
      }

      GURL best_icon = extensions::ExtensionIconSource::GetIconURL(
          extension,
          util::kPreferredIconSize,
          ExtensionIconSet::MATCH_BIGGER,
          false,  // grayscale
          NULL);  // exists
      if (!best_icon.is_empty())
        task->SetString("iconUrl", best_icon.spec());
      else
        task->SetString("iconUrl", kDefaultIcon);

      task->SetBoolean("driveApp", false);
      result_list->Append(task);
    }
  }

  return true;
}

bool GetFileTasksFunction::RunImpl() {
  // First argument is the list of files to get tasks for.
  ListValue* files_list = NULL;
  if (!args_->GetList(0, &files_list))
    return false;

  if (files_list->GetSize() == 0)
    return false;

  // Second argument is the list of mime types of each of the files in the list.
  ListValue* mime_types_list = NULL;
  if (!args_->GetList(1, &mime_types_list))
    return false;

  // MIME types can either be empty, or there needs to be one for each file.
  if (mime_types_list->GetSize() != files_list->GetSize() &&
      mime_types_list->GetSize() != 0)
    return false;

  content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
  scoped_refptr<fileapi::FileSystemContext> file_system_context =
      BrowserContext::GetStoragePartition(profile(), site_instance)->
      GetFileSystemContext();

  // Collect all the URLs, convert them to GURLs, and crack all the urls into
  // file paths.
  FileInfoList info_list;
  std::vector<GURL> file_urls;
  std::vector<base::FilePath> file_paths;
  bool has_google_document = false;
  for (size_t i = 0; i < files_list->GetSize(); ++i) {
    FileInfo info;
    std::string file_url_str;
    if (!files_list->GetString(i, &file_url_str))
      return false;

    if (mime_types_list->GetSize() != 0 &&
        !mime_types_list->GetString(i, &info.mime_type))
      return false;

    GURL file_url(file_url_str);
    fileapi::FileSystemURL file_system_url(
        file_system_context->CrackURL(file_url));
    if (!chromeos::FileSystemBackend::CanHandleURL(file_system_url))
      continue;

    file_urls.push_back(file_url);
    file_paths.push_back(file_system_url.path());

    info.file_url = file_url;
    info.file_path = file_system_url.path();
    info_list.push_back(info);

    if (google_apis::ResourceEntry::ClassifyEntryKindByFileExtension(
            info.file_path) &
        google_apis::ResourceEntry::KIND_OF_GOOGLE_DOCUMENT) {
      has_google_document = true;
    }
  }

  ListValue* result_list = new ListValue();
  SetResult(result_list);

  // Find the Drive apps first, because we want them to take precedence
  // when setting the default app.
  bool default_already_set = false;
  // Google document are not opened by drive apps but file manager.
  if (!has_google_document) {
    if (!FindDriveAppTasks(info_list, result_list, &default_already_set))
      return false;
  }

  // Take the union of platform app file handlers, and all previous Drive
  // and extension tasks. As above, we know there aren't duplicates because
  // they're entirely different kinds of
  // tasks.
  if (!FindAppTasks(file_paths, result_list, &default_already_set))
    return false;

  // Take the union of Drive and extension tasks: Because any Drive tasks we
  // found must apply to all of the files (intersection), and because the same
  // is true of the extensions, we simply take the union of two lists by adding
  // the extension tasks to the Drive task list. We know there aren't duplicates
  // because they're entirely different kinds of tasks, but there could be both
  // kinds of tasks for a file type (an image file, for instance).
  file_tasks::FileBrowserHandlerList common_tasks;
  file_tasks::FileBrowserHandlerList default_tasks;
  if (!file_tasks::FindCommonTasks(profile_, file_urls, &common_tasks))
    return false;
  file_tasks::FindDefaultTasks(profile_, file_paths,
                                      common_tasks, &default_tasks);

  ExtensionService* service =
      extensions::ExtensionSystem::Get(profile_)->extension_service();
  for (file_tasks::FileBrowserHandlerList::const_iterator iter =
           common_tasks.begin();
       iter != common_tasks.end();
       ++iter) {
    const FileBrowserHandler* handler = *iter;
    const std::string extension_id = handler->extension_id();
    const Extension* extension = service->GetExtensionById(extension_id, false);
    CHECK(extension);
    DictionaryValue* task = new DictionaryValue;
    task->SetString("taskId", file_tasks::MakeTaskID(
        extension_id, file_tasks::kTaskFile, handler->id()));
    task->SetString("title", handler->title());
    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
    // manifest instead of the default extension icon.
    GURL icon = extensions::ExtensionIconSource::GetIconURL(
        extension,
        extension_misc::EXTENSION_ICON_BITTY,
        ExtensionIconSet::MATCH_BIGGER,
        false,  // grayscale
        NULL);  // exists
    task->SetString("iconUrl", icon.spec());
    task->SetBoolean("driveApp", false);

    // Only set the default if there isn't already a default set.
    if (!default_already_set &&
        std::find(default_tasks.begin(), default_tasks.end(), *iter) !=
        default_tasks.end()) {
      task->SetBoolean("isDefault", true);
      default_already_set = true;
    } else {
      task->SetBoolean("isDefault", false);
    }

    result_list->Append(task);
  }

  SendResponse(true);
  return true;
}

SetDefaultTaskFunction::SetDefaultTaskFunction() {
}

SetDefaultTaskFunction::~SetDefaultTaskFunction() {
}

bool SetDefaultTaskFunction::RunImpl() {
  // First param is task id that was to the extension with setDefaultTask call.
  std::string task_id;
  if (!args_->GetString(0, &task_id) || !task_id.size())
    return false;

  base::ListValue* file_url_list;
  if (!args_->GetList(1, &file_url_list))
    return false;

  content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
  scoped_refptr<fileapi::FileSystemContext> context =
      BrowserContext::GetStoragePartition(profile(), site_instance)->
      GetFileSystemContext();

  std::set<std::string> suffixes =
      GetUniqueSuffixes(file_url_list, context.get());

  // MIME types are an optional parameter.
  base::ListValue* mime_type_list;
  std::set<std::string> mime_types;
  if (args_->GetList(2, &mime_type_list) && !mime_type_list->empty()) {
    if (mime_type_list->GetSize() != file_url_list->GetSize())
      return false;
    mime_types = GetUniqueMimeTypes(mime_type_list);
  }

  if (VLOG_IS_ON(1))
    LogDefaultTask(mime_types, suffixes, task_id);

  // If there weren't any mime_types, and all the suffixes were blank,
  // then we "succeed", but don't actually associate with anything.
  // Otherwise, any time we set the default on a file with no extension
  // on the local drive, we'd fail.
  // TODO(gspencer): Fix file manager so that it never tries to set default in
  // cases where extensionless local files are part of the selection.
  if (suffixes.empty() && mime_types.empty()) {
    SetResult(new base::FundamentalValue(true));
    return true;
  }

  file_tasks::UpdateDefaultTask(profile_, task_id, suffixes, mime_types);

  return true;
}

ViewFilesFunction::ViewFilesFunction() {
}

ViewFilesFunction::~ViewFilesFunction() {
}

bool ViewFilesFunction::RunImpl() {
  if (args_->GetSize() < 1) {
    return false;
  }

  ListValue* path_list = NULL;
  args_->GetList(0, &path_list);
  DCHECK(path_list);

  std::vector<base::FilePath> files;
  for (size_t i = 0; i < path_list->GetSize(); ++i) {
    std::string url_as_string;
    path_list->GetString(i, &url_as_string);
    base::FilePath path = util::GetLocalPathFromURL(
        render_view_host(), profile(), GURL(url_as_string));
    if (path.empty())
      return false;
    files.push_back(path);
  }

  Browser* browser = chrome::FindOrCreateTabbedBrowser(
      profile_, chrome::HOST_DESKTOP_TYPE_ASH);
  bool success = browser;

  if (browser) {
    for (size_t i = 0; i < files.size(); ++i) {
      bool handled = util::ExecuteBuiltinHandler(browser, files[i]);
      if (!handled && files.size() == 1)
        success = false;
    }
  }

  SetResult(Value::CreateBooleanValue(success));
  SendResponse(true);
  return true;
}

}  // namespace file_manager
