// 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/media_galleries/fileapi/picasa_file_util.h"

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/bind_helpers.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
#include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h"
#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
#include "chrome/common/media_galleries/picasa_types.h"
#include "content/public/browser/browser_thread.h"
#include "webkit/browser/fileapi/file_system_operation_context.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/browser/fileapi/native_file_util.h"
#include "webkit/common/fileapi/file_system_util.h"

using base::FilePath;
using fileapi::DirectoryEntry;
using fileapi::FileSystemOperationContext;
using fileapi::FileSystemURL;

namespace picasa {

namespace {

base::PlatformFileError FindAlbumInfo(const std::string& key,
                                      const AlbumMap* map,
                                      AlbumInfo* album_info) {
  if (!map)
    return base::PLATFORM_FILE_ERROR_FAILED;

  AlbumMap::const_iterator it = map->find(key);

  if (it == map->end())
    return base::PLATFORM_FILE_ERROR_NOT_FOUND;

  if (album_info != NULL)
    *album_info = it->second;

  return base::PLATFORM_FILE_OK;
}

PicasaDataProvider::DataType GetDataTypeForURL(
    const fileapi::FileSystemURL& url) {
  std::vector<std::string> components;
  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);

  if (components.size() >= 2 && components[0] == kPicasaDirAlbums)
    return PicasaDataProvider::ALBUMS_IMAGES_DATA;

  return PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA;
}

}  // namespace

const char kPicasaDirAlbums[]  = "albums";
const char kPicasaDirFolders[] = "folders";

PicasaFileUtil::PicasaFileUtil(MediaPathFilter* media_path_filter)
    : NativeMediaFileUtil(media_path_filter),
      weak_factory_(this) {
}

PicasaFileUtil::~PicasaFileUtil() {}

void PicasaFileUtil::GetFileInfoOnTaskRunnerThread(
    scoped_ptr<fileapi::FileSystemOperationContext> context,
    const fileapi::FileSystemURL& url,
    const GetFileInfoCallback& callback) {
  GetDataProvider()->RefreshData(
      GetDataTypeForURL(url),
      base::Bind(&PicasaFileUtil::GetFileInfoWithFreshDataProvider,
                 weak_factory_.GetWeakPtr(),
                 base::Passed(&context),
                 url,
                 callback));
}

void PicasaFileUtil::ReadDirectoryOnTaskRunnerThread(
    scoped_ptr<fileapi::FileSystemOperationContext> context,
    const fileapi::FileSystemURL& url,
    const ReadDirectoryCallback& callback) {
  GetDataProvider()->RefreshData(
      GetDataTypeForURL(url),
      base::Bind(&PicasaFileUtil::ReadDirectoryWithFreshDataProvider,
                 weak_factory_.GetWeakPtr(),
                 base::Passed(&context),
                 url,
                 callback));
}

base::PlatformFileError PicasaFileUtil::GetFileInfoSync(
    FileSystemOperationContext* context, const FileSystemURL& url,
    base::PlatformFileInfo* file_info, base::FilePath* platform_path) {
  DCHECK(context);
  DCHECK(file_info);

  if (platform_path)
    *platform_path = base::FilePath();

  std::vector<std::string> components;
  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);

  switch (components.size()) {
    case 0:
      // Root directory.
      file_info->is_directory = true;
      return base::PLATFORM_FILE_OK;
    case 1:
      if (components[0] == kPicasaDirAlbums ||
          components[0] == kPicasaDirFolders) {
        file_info->is_directory = true;
        return base::PLATFORM_FILE_OK;
      }

      break;
    case 2:
      if (components[0] == kPicasaDirAlbums) {
        scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums();
        base::PlatformFileError error =
            FindAlbumInfo(components[1], album_map.get(), NULL);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        file_info->is_directory = true;
        return base::PLATFORM_FILE_OK;
      }

      if (components[0] == kPicasaDirFolders) {
        return NativeMediaFileUtil::GetFileInfoSync(context, url, file_info,
                                                    platform_path);
      }
      break;
    case 3:
      // NativeMediaFileUtil::GetInfo calls into virtual function
      // PicasaFileUtil::GetLocalFilePath, and that will handle both
      // album contents and folder contents.
      base::PlatformFileError result = NativeMediaFileUtil::GetFileInfoSync(
          context, url, file_info, platform_path);

      DCHECK(components[0] == kPicasaDirAlbums ||
             components[0] == kPicasaDirFolders ||
             result == base::PLATFORM_FILE_ERROR_NOT_FOUND);

      return result;
  }

  return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}

base::PlatformFileError PicasaFileUtil::ReadDirectorySync(
    fileapi::FileSystemOperationContext* context,
    const fileapi::FileSystemURL& url,
    EntryList* file_list) {
  DCHECK(context);
  DCHECK(file_list);
  DCHECK(file_list->empty());

  base::PlatformFileInfo file_info;
  base::FilePath platform_directory_path;
  base::PlatformFileError error = GetFileInfoSync(
      context, url, &file_info, &platform_directory_path);

  if (error != base::PLATFORM_FILE_OK)
    return error;

  if (!file_info.is_directory)
    return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;

  std::vector<std::string> components;
  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);

  switch (components.size()) {
    case 0: {
      // Root directory.
      file_list->push_back(
          DirectoryEntry(kPicasaDirAlbums, DirectoryEntry::DIRECTORY, 0,
                         base::Time()));
      file_list->push_back(
          DirectoryEntry(kPicasaDirFolders, DirectoryEntry::DIRECTORY, 0,
                         base::Time()));
      break;
    }
    case 1:
      if (components[0] == kPicasaDirAlbums) {
        scoped_ptr<AlbumMap> albums = GetDataProvider()->GetAlbums();
        if (!albums)
          return base::PLATFORM_FILE_ERROR_NOT_FOUND;

        for (AlbumMap::const_iterator it = albums->begin();
             it != albums->end(); ++it) {
          file_list->push_back(
              DirectoryEntry(it->first, DirectoryEntry::DIRECTORY, 0,
                             it->second.timestamp));
        }
      } else if (components[0] == kPicasaDirFolders) {
        scoped_ptr<AlbumMap> folders = GetDataProvider()->GetFolders();
        if (!folders)
          return base::PLATFORM_FILE_ERROR_NOT_FOUND;

        for (AlbumMap::const_iterator it = folders->begin();
             it != folders->end(); ++it) {
          file_list->push_back(
              DirectoryEntry(it->first, DirectoryEntry::DIRECTORY, 0,
                             it->second.timestamp));
        }
      }
      break;
    case 2:
      if (components[0] == kPicasaDirAlbums) {
        scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums();
        AlbumInfo album_info;
        base::PlatformFileError error =
            FindAlbumInfo(components[1], album_map.get(), &album_info);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        scoped_ptr<AlbumImages> album_images =
            GetDataProvider()->FindAlbumImages(album_info.uid, &error);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        for (AlbumImages::const_iterator it = album_images->begin();
             it != album_images->end();
             ++it) {
          fileapi::DirectoryEntry entry;
          base::PlatformFileInfo info;

          // Simply skip files that we can't get info on.
          if (fileapi::NativeFileUtil::GetFileInfo(it->second, &info) !=
              base::PLATFORM_FILE_OK) {
            continue;
          }

          file_list->push_back(DirectoryEntry(
              it->first, DirectoryEntry::FILE, info.size, info.last_modified));
        }
      }

      if (components[0] == kPicasaDirFolders) {
        EntryList super_list;
        base::PlatformFileError error =
            NativeMediaFileUtil::ReadDirectorySync(context, url, &super_list);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        for (EntryList::const_iterator it = super_list.begin();
             it != super_list.end(); ++it) {
          if (!it->is_directory)
            file_list->push_back(*it);
        }
      }

      break;
  }

  return base::PLATFORM_FILE_OK;
}

base::PlatformFileError PicasaFileUtil::GetLocalFilePath(
    FileSystemOperationContext* context, const FileSystemURL& url,
    base::FilePath* local_file_path) {
  DCHECK(local_file_path);
  DCHECK(url.is_valid());
  std::vector<std::string> components;
  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);

  switch (components.size()) {
    case 2:
      if (components[0] == kPicasaDirFolders) {
        scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetFolders();
        AlbumInfo album_info;
        base::PlatformFileError error =
            FindAlbumInfo(components[1], album_map.get(), &album_info);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        *local_file_path = album_info.path;
        return base::PLATFORM_FILE_OK;
      }
      break;
    case 3:
      if (components[0] == kPicasaDirAlbums) {
        scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums();
        AlbumInfo album_info;
        base::PlatformFileError error =
            FindAlbumInfo(components[1], album_map.get(), &album_info);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        scoped_ptr<AlbumImages> album_images =
            GetDataProvider()->FindAlbumImages(album_info.uid, &error);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        AlbumImages::const_iterator it = album_images->find(components[2]);
        if (it == album_images->end())
          return base::PLATFORM_FILE_ERROR_NOT_FOUND;

        *local_file_path = it->second;
        return base::PLATFORM_FILE_OK;
      }

      if (components[0] == kPicasaDirFolders) {
        scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetFolders();
        AlbumInfo album_info;
        base::PlatformFileError error =
            FindAlbumInfo(components[1], album_map.get(), &album_info);
        if (error != base::PLATFORM_FILE_OK)
          return error;

        // Not part of this class's mandate to check that it actually exists.
        *local_file_path = album_info.path.Append(url.path().BaseName());
        return base::PLATFORM_FILE_OK;
      }

      return base::PLATFORM_FILE_ERROR_NOT_FOUND;
      break;
  }

  // All other cases don't have a local path. The valid cases should be
  // intercepted by GetFileInfo()/CreateFileEnumerator(). Invalid cases
  // return a NOT_FOUND error.
  return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}

void PicasaFileUtil::GetFileInfoWithFreshDataProvider(
    scoped_ptr<fileapi::FileSystemOperationContext> context,
    const fileapi::FileSystemURL& url,
    const GetFileInfoCallback& callback,
    bool success) {
  if (!success) {
    content::BrowserThread::PostTask(
        content::BrowserThread::IO,
        FROM_HERE,
        base::Bind(
            callback, base::PLATFORM_FILE_ERROR_IO, base::PlatformFileInfo()));
    return;
  }
  NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
      context.Pass(), url, callback);
}

void PicasaFileUtil::ReadDirectoryWithFreshDataProvider(
    scoped_ptr<fileapi::FileSystemOperationContext> context,
    const fileapi::FileSystemURL& url,
    const ReadDirectoryCallback& callback,
    bool success) {
  if (!success) {
    content::BrowserThread::PostTask(
        content::BrowserThread::IO,
        FROM_HERE,
        base::Bind(callback, base::PLATFORM_FILE_ERROR_IO, EntryList(), false));
    return;
  }
  NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
      context.Pass(), url, callback);
}

PicasaDataProvider* PicasaFileUtil::GetDataProvider() {
  return ImportedMediaGalleryRegistry::PicasaDataProvider();
}

}  // namespace picasa
