// Copyright (c) 2011 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 "cros-disks/cros_disks_server.h"

#include <base/logging.h>
#include <chromeos/dbus/service_constants.h>

#include "cros-disks/archive_manager.h"
#include "cros-disks/device_event.h"
#include "cros-disks/disk.h"
#include "cros-disks/disk_manager.h"
#include "cros-disks/format_manager.h"
#include "cros-disks/platform.h"
#include "cros-disks/rename_manager.h"

using std::string;
using std::vector;

namespace cros_disks {

CrosDisksServer::CrosDisksServer(DBus::Connection& connection,  // NOLINT
                                 Platform* platform,
                                 DiskManager* disk_manager,
                                 FormatManager* format_manager,
                                 RenameManager* rename_manager)
    : DBus::ObjectAdaptor(connection, kCrosDisksServicePath),
      platform_(platform),
      disk_manager_(disk_manager),
      format_manager_(format_manager),
      rename_manager_(rename_manager) {
  CHECK(platform_) << "Invalid platform object";
  CHECK(disk_manager_) << "Invalid disk manager object";
  CHECK(format_manager_) << "Invalid format manager object";
  CHECK(rename_manager_) << "Invalid rename manager object";

  format_manager_->set_observer(this);
  rename_manager_->set_observer(this);
}

void CrosDisksServer::RegisterMountManager(MountManager* mount_manager) {
  CHECK(mount_manager) << "Invalid mount manager object";
  mount_managers_.push_back(mount_manager);
}

void CrosDisksServer::Format(const string& path,
                             const string& filesystem_type,
                             const vector<string>& options,
                             DBus::Error& error) {  // NOLINT
  FormatErrorType error_type = FORMAT_ERROR_NONE;
  Disk disk;
  if (!disk_manager_->GetDiskByDevicePath(path, &disk)) {
    error_type = FORMAT_ERROR_INVALID_DEVICE_PATH;
  } else if (disk.is_on_boot_device) {
    error_type = FORMAT_ERROR_DEVICE_NOT_ALLOWED;
  } else {
    error_type = format_manager_->StartFormatting(path, disk.device_file,
                                                  filesystem_type);
  }

  if (error_type != FORMAT_ERROR_NONE) {
    LOG(ERROR) << "Could not format device '" << path << "' as filesystem '"
               << filesystem_type << "'";
    FormatCompleted(error_type, path);
  }
}

void CrosDisksServer::Rename(const string& path,
                             const string& volume_name,
                             DBus::Error& error) {  // NOLINT
  RenameErrorType error_type = RENAME_ERROR_NONE;
  Disk disk;
  if (!disk_manager_->GetDiskByDevicePath(path, &disk)) {
    error_type = RENAME_ERROR_INVALID_DEVICE_PATH;
  } else if (disk.is_on_boot_device || disk.is_read_only) {
    error_type = RENAME_ERROR_DEVICE_NOT_ALLOWED;
  } else {
    error_type = rename_manager_->StartRenaming(
        path, disk.device_file, volume_name, disk.filesystem_type);
  }

  if (error_type != RENAME_ERROR_NONE) {
    LOG(ERROR) << "Could not rename device '" << path << "' as '" << volume_name
               << "'";
    RenameCompleted(error_type, path);
  }
}

MountManager* CrosDisksServer::FindMounter(const string& source_path) const {
  for (const auto& manager : mount_managers_) {
    if (manager->CanMount(source_path)) {
      return manager;
    }
  }
  return nullptr;
}

void CrosDisksServer::Mount(const string& path,
                            const string& filesystem_type,
                            const vector<string>& options,
                            DBus::Error& error) {  // NOLINT
  MountErrorType error_type = MOUNT_ERROR_INVALID_PATH;
  MountSourceType source_type = MOUNT_SOURCE_INVALID;
  string source_path;
  string mount_path;

  if (platform_->GetRealPath(path, &source_path)) {
    MountManager* mounter = FindMounter(source_path);
    if (mounter) {
      source_type = mounter->GetMountSourceType();
      error_type =
          mounter->Mount(source_path, filesystem_type, options, &mount_path);
    }
  }

  if (error_type != MOUNT_ERROR_NONE) {
    LOG(ERROR) << "Failed to mount '" << path << "'";
  }
  MountCompleted(error_type, path, source_type, mount_path);
}

void CrosDisksServer::Unmount(const string& path,
                              const vector<string>& options,
                              DBus::Error& error) {  // NOLINT
  MountErrorType error_type = MOUNT_ERROR_INVALID_PATH;
  for (const auto& manager : mount_managers_) {
    if (manager->CanUnmount(path)) {
      error_type = manager->Unmount(path, options);
      break;
    }
  }

  if (error_type != MOUNT_ERROR_NONE) {
    string message = "Failed to unmount '" + path + "'";
    error.set(kCrosDisksServiceError, message.c_str());
  }
}

void CrosDisksServer::UnmountAll(DBus::Error& error) {  // NOLINT
  DoUnmountAll();
}

void CrosDisksServer::DoUnmountAll() {
  for (const auto& manager : mount_managers_) {
    manager->UnmountAll();
  }
}

vector<string> CrosDisksServer::DoEnumerateDevices(
    bool auto_mountable_only) const {
  vector<Disk> disks = disk_manager_->EnumerateDisks();
  vector<string> devices;
  devices.reserve(disks.size());
  for (const auto& disk : disks) {
    if (!auto_mountable_only || disk.is_auto_mountable) {
      devices.push_back(disk.native_path);
    }
  }
  return devices;
}

vector<string> CrosDisksServer::EnumerateDevices(
    DBus::Error& error) {  // NOLINT
  return DoEnumerateDevices(false);
}

vector<string> CrosDisksServer::EnumerateAutoMountableDevices(
    DBus::Error& error) {  // NOLINT
  return DoEnumerateDevices(true);
}

vector<CrosDisksServer::DBusMountEntry> CrosDisksServer::EnumerateMountEntries(
    DBus::Error& error) {  // NOLINT
  vector<DBusMountEntry> dbus_mount_entries;
  for (const auto& manager : mount_managers_) {
    for (const auto& mount_entry : manager->GetMountEntries()) {
      dbus_mount_entries.push_back(
          {mount_entry.error_type, mount_entry.source_path,
           mount_entry.source_type, mount_entry.mount_path});
    }
  }
  return dbus_mount_entries;
}

std::map<std::string, DBus::Variant> CrosDisksServer::GetDeviceProperties(
    const string& device_path,
    DBus::Error& error) {  // NOLINT
  Disk disk;
  if (!disk_manager_->GetDiskByDevicePath(device_path, &disk)) {
    string message = "Could not get the properties of device " + device_path;
    LOG(ERROR) << message;
    error.set(kCrosDisksServiceError, message.c_str());
  }

  std::map<std::string, DBus::Variant> properties;
  properties[kDeviceIsDrive].writer().append_bool(disk.is_drive);
  properties[kDevicePresentationHide].writer().append_bool(disk.is_hidden);
  properties[kDeviceIsMounted].writer().append_bool(disk.IsMounted());
  properties[kDeviceIsMediaAvailable].writer().append_bool(
      disk.is_media_available);
  properties[kDeviceIsOnBootDevice].writer().append_bool(
      disk.is_on_boot_device);
  properties[kDeviceIsOnRemovableDevice].writer().append_bool(
      disk.is_on_removable_device);
  properties[kDeviceIsVirtual].writer().append_bool(disk.is_virtual);
  properties[kNativePath].writer().append_string(disk.native_path.c_str());
  properties[kDeviceFile].writer().append_string(disk.device_file.c_str());
  properties[kIdUuid].writer().append_string(disk.uuid.c_str());
  properties[kIdLabel].writer().append_string(disk.label.c_str());
  properties[kVendorId].writer().append_string(disk.vendor_id.c_str());
  properties[kVendorName].writer().append_string(disk.vendor_name.c_str());
  properties[kProductId].writer().append_string(disk.product_id.c_str());
  properties[kProductName].writer().append_string(disk.product_name.c_str());
  properties[kDriveModel].writer().append_string(disk.drive_model.c_str());
  properties[kDriveIsRotational].writer().append_bool(disk.is_rotational);
  properties[kDeviceMediaType].writer().append_uint32(disk.media_type);
  properties[kDeviceSize].writer().append_uint64(disk.device_capacity);
  properties[kDeviceIsReadOnly].writer().append_bool(disk.is_read_only);
  properties[kFileSystemType].writer().append_string(
      disk.filesystem_type.c_str());
  DBus::MessageIter iter = properties[kDeviceMountPaths].writer();
  iter << disk.mount_paths;
  return properties;
}

void CrosDisksServer::OnFormatCompleted(const string& device_path,
                                        FormatErrorType error_type) {
  FormatCompleted(error_type, device_path);
}

void CrosDisksServer::OnRenameCompleted(const string& device_path,
                                        RenameErrorType error_type) {
  RenameCompleted(error_type, device_path);
}

void CrosDisksServer::OnScreenIsLocked() {
  // no-op
}

void CrosDisksServer::OnScreenIsUnlocked() {
  // no-op
}

void CrosDisksServer::OnSessionStarted() {
  for (const auto& manager : mount_managers_) {
    manager->StartSession();
  }
}

void CrosDisksServer::OnSessionStopped() {
  for (const auto& manager : mount_managers_) {
    manager->StopSession();
  }
}

void CrosDisksServer::DispatchDeviceEvent(const DeviceEvent& event) {
  switch (event.event_type) {
    case DeviceEvent::kDeviceAdded:
      DeviceAdded(event.device_path);
      break;
    case DeviceEvent::kDeviceScanned:
      DeviceScanned(event.device_path);
      break;
    case DeviceEvent::kDeviceRemoved:
      DeviceRemoved(event.device_path);
      break;
    case DeviceEvent::kDiskAdded:
      DiskAdded(event.device_path);
      break;
    case DeviceEvent::kDiskChanged:
      DiskChanged(event.device_path);
      break;
    case DeviceEvent::kDiskRemoved:
      DiskRemoved(event.device_path);
      break;
    default:
      break;
  }
}

}  // namespace cros_disks
