// Copyright (c) 2012 The Chromium OS 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 "mtpd/mtpd_server_impl.h"

#include <base/logging.h>
#include <base/rand_util.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/tracked_objects.h>
#include <chromeos/dbus/service_constants.h>

namespace mtpd {

namespace {

// Maximum number of bytes to read from the device at one time. This is set low
// enough such that a reasonable device can read this much data before D-Bus
// times out.
const uint32_t kMaxReadCount = 1024 * 1024;

void AddError(brillo::ErrorPtr* error,
              const tracked_objects::Location& location,
              const std::string& message) {
  brillo::Error::AddTo(error,
                       location,
                       brillo::errors::dbus::kDomain,
                       kMtpdServiceError,
                       message);
}

void AddInvalidHandleError(brillo::ErrorPtr* error,
                           const tracked_objects::Location& location,
                           const std::string& handle) {
  brillo::Error::AddToPrintf(error,
                             location,
                             brillo::errors::dbus::kDomain,
                             kMtpdServiceError,
                             "Invalid handle %s", handle.c_str());
}

}  // namespace

MtpdServer::MtpdServer(scoped_refptr<dbus::Bus> bus)
    : org::chromium::MtpdAdaptor(this),
      dbus_object_(nullptr, bus, dbus::ObjectPath(kMtpdServicePath)),
      device_manager_(this) {}

MtpdServer::~MtpdServer() {}

std::vector<std::string> MtpdServer::EnumerateStorages() {
  return device_manager_.EnumerateStorages();
}

std::vector<uint8_t> MtpdServer::GetStorageInfo(
    const std::string& storage_name) {
  const StorageInfo* info = device_manager_.GetStorageInfo(storage_name);
  return info ? info->ToDBusFormat() : StorageInfo().ToDBusFormat();
}

std::vector<uint8_t> MtpdServer::GetStorageInfoFromDevice(
    const std::string& storage_name) {
  const StorageInfo* info =
      device_manager_.GetStorageInfoFromDevice(storage_name);
  return info ? info->ToDBusFormat() : StorageInfo().ToDBusFormat();
}

bool MtpdServer::OpenStorage(brillo::ErrorPtr* error,
                             const std::string& storage_name,
                             const std::string& mode,
                             std::string* id) {
  if (!(mode == kReadOnlyMode || mode == kReadWriteMode)) {
    brillo::Error::AddToPrintf(error,
                               FROM_HERE,
                               brillo::errors::dbus::kDomain,
                               kMtpdServiceError,
                               "Cannot open %s in mode: %s",
                               storage_name.c_str(), mode.c_str());
    return false;
  }

  if (!device_manager_.HasStorage(storage_name)) {
    brillo::Error::AddToPrintf(error,
                               FROM_HERE,
                               brillo::errors::dbus::kDomain,
                               kMtpdServiceError,
                               "Cannot open unknown storage %s",
                               storage_name.c_str());
    return false;
  }

  std::string new_id;
  uint32_t random_data[4];
  do {
    base::RandBytes(random_data, sizeof(random_data));
    new_id = base::HexEncode(random_data, sizeof(random_data));
  } while (base::ContainsKey(handle_map_, new_id));

  handle_map_.insert(
      std::make_pair(new_id, std::make_pair(storage_name, mode)));
  *id = new_id;
  return true;
}

bool MtpdServer::CloseStorage(brillo::ErrorPtr* error,
                              const std::string& handle) {
  if (handle_map_.erase(handle) == 0) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  return true;
}

bool MtpdServer::ReadDirectoryEntryIds(
      brillo::ErrorPtr* error,
      const std::string& handle,
      uint32_t file_id,
      std::vector<uint32_t>* directory_listing) {
  std::string storage_name = LookupHandle(handle);
  if (storage_name.empty()) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  if (!device_manager_.ReadDirectoryEntryIds(storage_name, file_id,
                                             directory_listing)) {
    AddError(error, FROM_HERE, "ReadDirectoryEntryIds failed");
    return false;
  }

  return true;
}

bool MtpdServer::GetFileInfo(brillo::ErrorPtr* error,
                             const std::string& handle,
                             const std::vector<uint32_t>& file_ids,
                             std::vector<uint8_t>* serialized_file_entries) {
  if (file_ids.empty()) {
    AddError(error, FROM_HERE, "GetFileInfo called with no file ids");
    return false;
  }

  std::string storage_name = LookupHandle(handle);
  if (storage_name.empty()) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  std::vector<FileEntry> file_info;
  if (!device_manager_.GetFileInfo(storage_name, file_ids, &file_info)) {
    AddError(error, FROM_HERE, "GetFileInfo failed");
    return false;
  }

  *serialized_file_entries = FileEntry::FileEntriesToDBusFormat(file_info);
  return true;
}

bool MtpdServer::ReadFileChunk(brillo::ErrorPtr* error,
                               const std::string& handle,
                               uint32_t file_id,
                               uint32_t offset,
                               uint32_t count,
                               std::vector<uint8_t>* file_contents) {
  if (count > kMaxReadCount || count == 0) {
    AddError(error, FROM_HERE, "Invalid count for ReadFileChunk");
    return false;
  }
  std::string storage_name = LookupHandle(handle);
  if (storage_name.empty()) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  if (!device_manager_.ReadFileChunk(storage_name, file_id, offset, count,
                                     file_contents)) {
    AddError(error, FROM_HERE, "ReadFileChunk failed");
    return false;
  }

  return true;
}

bool MtpdServer::CopyFileFromLocal(brillo::ErrorPtr* error,
                                   const std::string& handle,
                                   const base::ScopedFD& file_descriptor,
                                   uint32_t parent_id,
                                   const std::string& file_name) {
  const std::string storage_name = LookupHandle(handle);
  if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  if (!device_manager_.CopyFileFromLocal(storage_name, file_descriptor.get(),
                                         parent_id, file_name)) {
    AddError(error, FROM_HERE, "CopyFileFromLocal failed");
    return false;
  }

  return true;
}

bool MtpdServer::DeleteObject(brillo::ErrorPtr* error,
                              const std::string& handle,
                              uint32_t object_id) {
  const std::string storage_name = LookupHandle(handle);
  if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  if (!device_manager_.DeleteObject(storage_name, object_id)) {
    AddError(error, FROM_HERE, "DeleteObject failed");
    return false;
  }

  return true;
}

bool MtpdServer::RenameObject(brillo::ErrorPtr* error,
                              const std::string& handle,
                              uint32_t object_id,
                              const std::string& new_name) {
  const std::string storage_name = LookupHandle(handle);
  if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  if (!device_manager_.RenameObject(storage_name, object_id, new_name)) {
    AddError(error, FROM_HERE, "RenameObject failed");
    return false;
  }

  return true;
}

bool MtpdServer::CreateDirectory(brillo::ErrorPtr* error,
                                 const std::string& handle,
                                 uint32_t parent_id,
                                 const std::string& directory_name) {
  const std::string storage_name = LookupHandle(handle);
  if (storage_name.empty() || !IsOpenedWithWrite(handle)) {
    AddInvalidHandleError(error, FROM_HERE, handle);
    return false;
  }

  if (!device_manager_.CreateDirectory(storage_name, parent_id,
                                       directory_name)) {
    AddError(error, FROM_HERE, "CreateDirectory failed.");
    return false;
  }

  return true;
}

bool MtpdServer::IsAlive() {
  return true;
}

void MtpdServer::StorageAttached(const std::string& storage_name) {
  // Fire DBus signal.
  SendMTPStorageAttachedSignal(storage_name);
}

void MtpdServer::StorageDetached(const std::string& storage_name) {
  // Fire DBus signal.
  SendMTPStorageDetachedSignal(storage_name);
}

int MtpdServer::GetDeviceEventDescriptor() const {
  return device_manager_.GetDeviceEventDescriptor();
}

void MtpdServer::ProcessDeviceEvents() {
  device_manager_.ProcessDeviceEvents();
}

std::string MtpdServer::LookupHandle(const std::string& handle) {
  HandleMap::const_iterator it = handle_map_.find(handle);
  return (it == handle_map_.end()) ? std::string() : it->second.first;
}

bool MtpdServer::IsOpenedWithWrite(const std::string& handle) {
  HandleMap::const_iterator it = handle_map_.find(handle);
  return (it == handle_map_.end()) ? false
                                   : it->second.second == kReadWriteMode;
}

void MtpdServer::RegisterAsync(
    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
  RegisterWithDBusObject(&dbus_object_);
  dbus_object_.RegisterAsync(cb);
}

}  // namespace mtpd
