// Copyright 2014 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 "components/storage_monitor/media_storage_util.h"

#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "build/build_config.h"
#include "components/storage_monitor/removable_device_constants.h"
#include "components/storage_monitor/storage_monitor.h"
#include "content/public/browser/browser_thread.h"

namespace storage_monitor {

namespace {

#if !defined(OS_WIN)
const char kRootPath[] = "/";
#endif

typedef std::vector<StorageInfo> StorageInfoList;

base::FilePath::StringType FindRemovableStorageLocationById(
    const std::string& device_id) {
  StorageInfoList devices =
      StorageMonitor::GetInstance()->GetAllAvailableStorages();
  for (StorageInfoList::const_iterator it = devices.begin();
       it != devices.end(); ++it) {
    if (it->device_id() == device_id
        && StorageInfo::IsRemovableDevice(device_id))
      return it->location();
  }
  return base::FilePath::StringType();
}

void FilterAttachedDevicesOnBackgroundSequence(
    MediaStorageUtil::DeviceIdSet* devices) {
  MediaStorageUtil::DeviceIdSet missing_devices;

  for (auto it = devices->begin(); it != devices->end(); ++it) {
    StorageInfo::Type type;
    std::string unique_id;
    if (!StorageInfo::CrackDeviceId(*it, &type, &unique_id)) {
      missing_devices.insert(*it);
      continue;
    }

    if (type == StorageInfo::FIXED_MASS_STORAGE) {
      if (!base::PathExists(base::FilePath::FromUTF8Unsafe(unique_id)))
        missing_devices.insert(*it);
      continue;
    }

    if (!MediaStorageUtil::IsRemovableStorageAttached(*it))
      missing_devices.insert(*it);
  }

  for (auto it = missing_devices.begin(); it != missing_devices.end(); ++it) {
    devices->erase(*it);
  }
}

}  // namespace

// static
bool MediaStorageUtil::HasDcim(const base::FilePath& mount_point) {
  base::FilePath::StringType dcim_dir(kDCIMDirectoryName);
  if (!base::DirectoryExists(mount_point.Append(dcim_dir))) {
    // Check for lowercase 'dcim' as well.
    base::FilePath dcim_path_lower(
        mount_point.Append(base::ToLowerASCII(dcim_dir)));
    if (!base::DirectoryExists(dcim_path_lower))
      return false;
  }
  return true;
}

// static
bool MediaStorageUtil::CanCreateFileSystem(const std::string& device_id,
                                           const base::FilePath& path) {
  StorageInfo::Type type;
  if (!StorageInfo::CrackDeviceId(device_id, &type, nullptr))
    return false;

  if (type == StorageInfo::MAC_IMAGE_CAPTURE)
    return true;

  return !path.empty() && path.IsAbsolute() && !path.ReferencesParent();
}

// static
void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices,
                                             const base::Closure& done) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  base::PostTaskAndReply(
      FROM_HERE,
      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::BindOnce(&FilterAttachedDevicesOnBackgroundSequence, devices),
      done);
}

// TODO(kmadhusu) Write unit tests for GetDeviceInfoFromPath().
// static
bool MediaStorageUtil::GetDeviceInfoFromPath(const base::FilePath& path,
                                             StorageInfo* device_info,
                                             base::FilePath* relative_path) {
  DCHECK(device_info);
  DCHECK(relative_path);

  if (!path.IsAbsolute())
    return false;

  StorageInfo info;
  StorageMonitor* monitor = StorageMonitor::GetInstance();
  bool found_device = monitor->GetStorageInfoForPath(path, &info);

  if (found_device && StorageInfo::IsRemovableDevice(info.device_id())) {
    base::FilePath sub_folder_path;
    base::FilePath device_path(info.location());
    if (path != device_path) {
      bool success = device_path.AppendRelativePath(path, &sub_folder_path);
      DCHECK(success);
    }

    *device_info = info;
    *relative_path = sub_folder_path;
    return true;
  }

  // On Posix systems, there's one root so any absolute path could be valid.
  // TODO(gbillock): Delete this stanza? Posix systems should have the root
  // volume information. If not, we should move the below into the
  // right GetStorageInfoForPath implementations.
#if !defined(OS_POSIX)
  if (!found_device)
    return false;
#endif

  // Handle non-removable devices. Note: this is just overwriting
  // good values from StorageMonitor.
  // TODO(gbillock): Make sure return values from that class are definitive,
  // and don't do this here.
  info.set_device_id(
      StorageInfo::MakeDeviceId(StorageInfo::FIXED_MASS_STORAGE,
                                path.AsUTF8Unsafe()));
  *device_info = info;
  *relative_path = base::FilePath();
  return true;
}

// static
base::FilePath MediaStorageUtil::FindDevicePathById(
    const std::string& device_id) {
  StorageInfo::Type type;
  std::string unique_id;
  if (!StorageInfo::CrackDeviceId(device_id, &type, &unique_id))
    return base::FilePath();

  if (type == StorageInfo::FIXED_MASS_STORAGE) {
    // For this type, the unique_id is the path.
    return base::FilePath::FromUTF8Unsafe(unique_id);
  }

  // For ImageCapture, the synthetic filesystem will be rooted at a fake
  // top-level directory which is the device_id.
  if (type == StorageInfo::MAC_IMAGE_CAPTURE) {
#if !defined(OS_WIN)
    return base::FilePath(kRootPath + device_id);
#endif
  }

  DCHECK(type == StorageInfo::MTP_OR_PTP ||
         type == StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM ||
         type == StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM);
  return base::FilePath(FindRemovableStorageLocationById(device_id));
}

// static
bool MediaStorageUtil::IsRemovableStorageAttached(const std::string& id) {
  StorageMonitor* monitor = StorageMonitor::GetInstance();
  if (!monitor)
    return false;

  StorageInfoList devices = monitor->GetAllAvailableStorages();
  for (const auto& device : devices) {
    if (StorageInfo::IsRemovableDevice(id) && device.device_id() == id)
      return true;
  }
  return false;
}

}  // namespace storage_monitor
