// Copyright 2018 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 <arpa/inet.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>

#include <iostream>
#include <memory>
#include <string>
#include <utility>

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/check_op.h>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/message_loop/message_pump_type.h>
#include <base/notreached.h>
#include <base/run_loop.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_piece.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <base/system/sys_info.h>
#include <base/task/single_thread_task_executor.h>
#include <base/threading/thread_task_runner_handle.h>
#include <brillo/flag_helper.h>
#include <brillo/syslog_logging.h>
#include <chromeos/dbus/service_constants.h>
#include <crosvm/qcow_utils.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include <dbus/object_path.h>
#include <dbus/object_proxy.h>
#include <vm_cicerone/proto_bindings/cicerone_service.pb.h>

using std::string;

namespace {

constexpr int kDefaultTimeoutMs = 120 * 1000;

void OnSignalConnected(const std::string& interface_name,
                       const std::string& signal_name,
                       bool is_connected) {
  LOG(INFO) << "D-Bus signal " << (is_connected ? "" : "NOT ")
            << "connected for " << interface_name << ":" << signal_name;
}

void OnContainerCreatedCallback(
    base::RunLoop* run_loop,
    vm_tools::cicerone::LxdContainerCreatedSignal::Status* final_status,
    std::string* failure_reason,
    dbus::Signal* signal) {
  dbus::MessageReader reader(signal);
  vm_tools::cicerone::LxdContainerCreatedSignal lccs;
  if (!reader.PopArrayOfBytesAsProto(&lccs)) {
    LOG(ERROR) << "Failed parsing LxdContainerCreatedSignal proto";
    return;
  }

  *final_status = lccs.status();
  *failure_reason = lccs.failure_reason();
  run_loop->Quit();
}

void OnContainerStartingCallback(
    base::RunLoop* run_loop,
    vm_tools::cicerone::LxdContainerStartingSignal::Status* final_status,
    std::string* failure_reason,
    dbus::Signal* signal) {
  dbus::MessageReader reader(signal);
  vm_tools::cicerone::LxdContainerStartingSignal lcss;
  if (!reader.PopArrayOfBytesAsProto(&lcss)) {
    LOG(ERROR) << "Failed parsing LxdContainerStartingSignal proto";
    return;
  }

  switch (lcss.status()) {
    case vm_tools::cicerone::LxdContainerStartingSignal::STARTED:
    case vm_tools::cicerone::LxdContainerStartingSignal::CANCELLED:
    case vm_tools::cicerone::LxdContainerStartingSignal::FAILED:
      *final_status = lcss.status();
      *failure_reason = lcss.failure_reason();
      run_loop->Quit();
      break;
    default:
      break;
  }
}

int CreateLxdContainer(dbus::ObjectProxy* proxy,
                       const string& vm_name,
                       const string& container_name,
                       const string& owner_id,
                       string image_server,
                       string image_alias,
                       string rootfs_path,
                       string metadata_path) {
  LOG(INFO) << "Creating LXD container";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kCreateLxdContainerMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::CreateLxdContainerRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);
  request.set_image_server(std::move(image_server));
  request.set_image_alias(std::move(image_alias));
  request.set_rootfs_path(std::move(rootfs_path));
  request.set_metadata_path(std::move(metadata_path));

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode CreateLxdContainer protobuf";
    return -1;
  }

  // RunLoop so we can monitor the D-Bus signals coming back to determine when
  // container creation has actually finished.
  base::RunLoop run_loop;
  vm_tools::cicerone::LxdContainerCreatedSignal::Status final_status =
      vm_tools::cicerone::LxdContainerCreatedSignal::UNKNOWN;
  std::string failure_reason = "Timed out waiting for reply";
  proxy->ConnectToSignal(vm_tools::cicerone::kVmCiceroneInterface,
                         vm_tools::cicerone::kLxdContainerCreatedSignal,
                         base::BindRepeating(&OnContainerCreatedCallback,
                                             base::Unretained(&run_loop),
                                             &final_status, &failure_reason),
                         base::BindOnce(&OnSignalConnected));

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::CreateLxdContainerResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  vm_tools::cicerone::CreateLxdContainerResponse::Status status =
      response.status();
  if (status != vm_tools::cicerone::CreateLxdContainerResponse::CREATING &&
      status != vm_tools::cicerone::CreateLxdContainerResponse::EXISTS) {
    LOG(ERROR) << "Failed to create LXD container: "
               << response.failure_reason();
    return -1;
  }

  if (status == vm_tools::cicerone::CreateLxdContainerResponse::EXISTS) {
    LOG(INFO) << "Container " << container_name << " already existed";
    return 0;
  } else {
    // Start the RunLoop which'll get the D-Bus signal callbacks and set the
    // final result for us.
    LOG(INFO) << "Waiting for D-Bus signal for container creation status";
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMinutes(10));
    run_loop.Run();

    if (final_status ==
        vm_tools::cicerone::LxdContainerCreatedSignal::CREATED) {
      LOG(INFO) << "Created container " << container_name << " successfully";
      return 0;
    } else {
      LOG(ERROR) << "Failed to create LXD container: " << failure_reason;
      return -1;
    }
  }
}

int StartLxdContainer(dbus::ObjectProxy* proxy,
                      const string& vm_name,
                      const string& container_name,
                      const string& owner_id) {
  LOG(INFO) << "Starting LXD container";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kStartLxdContainerMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::StartLxdContainerRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode StartLxdContainer protobuf";
    return -1;
  }

  // RunLoop so we can monitor the D-Bus signals coming back to determine when
  // starting the container has actually finished.
  base::RunLoop run_loop;
  vm_tools::cicerone::LxdContainerStartingSignal::Status final_status =
      vm_tools::cicerone::LxdContainerStartingSignal::UNKNOWN;
  std::string failure_reason = "Timed out waiting for reply";
  proxy->ConnectToSignal(vm_tools::cicerone::kVmCiceroneInterface,
                         vm_tools::cicerone::kLxdContainerStartingSignal,
                         base::BindRepeating(&OnContainerStartingCallback,
                                             base::Unretained(&run_loop),
                                             &final_status, &failure_reason),
                         base::BindOnce(&OnSignalConnected));

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::StartLxdContainerResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  vm_tools::cicerone::StartLxdContainerResponse::Status status =
      response.status();
  if (status == vm_tools::cicerone::StartLxdContainerResponse::FAILED ||
      status == vm_tools::cicerone::StartLxdContainerResponse::UNKNOWN) {
    LOG(ERROR) << "Failed to start LXD container: "
               << response.failure_reason();
    return -1;
  }

  if (status == vm_tools::cicerone::StartLxdContainerResponse::RUNNING) {
    LOG(INFO) << "Container " << container_name << " already running";
    return 0;
  } else {
    if (status == vm_tools::cicerone::StartLxdContainerResponse::REMAPPING) {
      LOG(INFO) << "Container is remapping filesystem; this can take a while";
    } else {
      DCHECK_EQ(status,
                vm_tools::cicerone::StartLxdContainerResponse::STARTING);
    }
    // Start the RunLoop which'll get the D-Bus signal callbacks and set the
    // final result for us.
    LOG(INFO) << "Waiting for D-Bus signal for container start status";
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMinutes(10));
    run_loop.Run();

    if (final_status ==
        vm_tools::cicerone::LxdContainerStartingSignal::STARTED) {
      LOG(INFO) << "Started container " << container_name << " successfully";
      return 0;
    } else {
      LOG(ERROR) << "Failed to start LXD container: " << failure_reason;
      return -1;
    }

    LOG(INFO) << "Started container: " << container_name;
    return 0;
  }
}

int SetTimezone(dbus::ObjectProxy* proxy, const string& timezone_name) {
  LOG(INFO) << "Setting timezone for VMs to " << timezone_name;

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kSetTimezoneMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::SetTimezoneRequest request;
  request.set_timezone_name(timezone_name);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode SetTimezone protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::SetTimezoneResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }

  LOG(INFO) << "Successfully set timezone for " << response.successes()
            << " containers to " << timezone_name;

  int failure_count = response.failure_reasons_size();
  if (failure_count != 0) {
    LOG(ERROR) << "Received " << failure_count << " failures:";
    for (int i = 0; i < failure_count; i++) {
      LOG(ERROR) << response.failure_reasons(i);
    }
    return -1;
  }
  return 0;
}

int GetLxdContainerUsername(dbus::ObjectProxy* proxy,
                            const string& vm_name,
                            const string& container_name,
                            const string& owner_id) {
  LOG(INFO) << "Getting LXD container primary username";

  dbus::MethodCall method_call(
      vm_tools::cicerone::kVmCiceroneInterface,
      vm_tools::cicerone::kGetLxdContainerUsernameMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::GetLxdContainerUsernameRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode GetLxdContainerUsernameRequest protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::GetLxdContainerUsernameResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  vm_tools::cicerone::GetLxdContainerUsernameResponse::Status status =
      response.status();
  if (status != vm_tools::cicerone::GetLxdContainerUsernameResponse::SUCCESS) {
    LOG(ERROR) << "Failed to get primary username: "
               << response.failure_reason();
    return -1;
  }

  LOG(INFO) << "Container primary user is: " << response.username();
  return 0;
}

int SetUpLxdContainerUser(dbus::ObjectProxy* proxy,
                          const string& vm_name,
                          const string& container_name,
                          const string& owner_id,
                          string container_username) {
  LOG(INFO) << "Setting up LXD container user";

  dbus::MethodCall method_call(
      vm_tools::cicerone::kVmCiceroneInterface,
      vm_tools::cicerone::kSetUpLxdContainerUserMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::SetUpLxdContainerUserRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);
  request.set_container_username(std::move(container_username));

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode SetUpLxdContainerUser protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::SetUpLxdContainerUserResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  vm_tools::cicerone::SetUpLxdContainerUserResponse::Status status =
      response.status();
  if (status != vm_tools::cicerone::SetUpLxdContainerUserResponse::EXISTS &&
      status != vm_tools::cicerone::SetUpLxdContainerUserResponse::SUCCESS) {
    LOG(ERROR) << "Failed to set up user: " << response.failure_reason();
    return -1;
  }

  if (status == vm_tools::cicerone::SetUpLxdContainerUserResponse::EXISTS) {
    LOG(INFO) << "Container user already exists";
    return 0;
  } else {
    LOG(INFO) << "Created user in container";
    return 0;
  }
}

int LaunchApplication(dbus::ObjectProxy* proxy,
                      string owner_id,
                      string name,
                      string container_name,
                      string application) {
  if (application.empty()) {
    LOG(ERROR) << "--application is required";
    return -1;
  }

  LOG(INFO) << "Starting application " << application << " in '" << name << ":"
            << container_name << "'";

  dbus::MethodCall method_call(
      vm_tools::cicerone::kVmCiceroneInterface,
      vm_tools::cicerone::kLaunchContainerApplicationMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::LaunchContainerApplicationRequest request;
  request.set_owner_id(owner_id);
  request.set_vm_name(name);
  request.set_container_name(container_name);
  request.set_desktop_file_id(application);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode LaunchContainerApplicationRequest protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::LaunchContainerApplicationResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }

  if (!response.success()) {
    LOG(ERROR) << "Failed to launch application: " << response.failure_reason();
    return -1;
  }

  LOG(INFO) << "Launched application " << application << " in '" << name << ":"
            << container_name << "'";

  return 0;
}

void Write(const std::string& output_filepath, const std::string& content) {
  int content_size = content.size();
  if (content_size != base::WriteFile(base::FilePath(output_filepath),
                                      content.c_str(), content_size)) {
    LOG(ERROR) << "Failed to write to file " << output_filepath;
  }
}

int GetIcon(dbus::ObjectProxy* proxy,
            string owner_id,
            string name,
            string container_name,
            string application,
            int icon_size,
            int scale,
            string output_filepath) {
  if (application.empty()) {
    LOG(ERROR) << "--application is required";
    return -1;
  }

  if (output_filepath.empty()) {
    LOG(ERROR) << "--output_filepath is required";
    return -1;
  }

  LOG(INFO) << "Getting icon for " << application << " in '" << name << ":"
            << container_name << "'";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kGetContainerAppIconMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::ContainerAppIconRequest request;
  request.set_owner_id(owner_id);
  request.set_vm_name(name);
  request.set_container_name(container_name);
  request.add_desktop_file_ids(application);
  request.set_size(icon_size);
  request.set_scale(scale);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode ContainerAppIconRequest protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::ContainerAppIconResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }

  // This should have up to one icon since the input has only one application
  // file ID.
  CHECK_LE(response.icons_size(), 1);
  for (vm_tools::cicerone::DesktopIcon icon : response.icons()) {
    if (!icon.icon().empty())
      Write(output_filepath, icon.icon());
  }

  return 0;
}

int GetInfo(dbus::ObjectProxy* proxy) {
  LOG(INFO) << "Getting information";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kGetDebugInformationMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::GetDebugInformationRequest request;

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode GetDebugInformationRequest protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::GetDebugInformationResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }

  std::cout << response.debug_information();

  return 0;
}

int GetLinuxPackageInfo(dbus::ObjectProxy* proxy,
                        const string& vm_name,
                        const string& container_name,
                        const string& owner_id,
                        string file_path) {
  if (file_path.empty()) {
    LOG(ERROR) << "--file_path is required";
    return -1;
  }
  LOG(INFO) << "Getting Linux package info";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kGetLinuxPackageInfoMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::LinuxPackageInfoRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);
  request.set_file_path(file_path);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode LinuxPackageInfoRequest protobuf";
    return -1;
  }

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::LinuxPackageInfoResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  if (!response.success()) {
    LOG(ERROR) << "Failure getting Linux package info: "
               << response.failure_reason();
    return -1;
  }
  LOG(INFO) << "Linux package info for: " << file_path;
  LOG(INFO) << "Package ID: " << response.package_id();
  LOG(INFO) << "License: " << response.license();
  LOG(INFO) << "Description: " << response.description();
  LOG(INFO) << "Project URL: " << response.project_url();
  LOG(INFO) << "Size(bytes): " << response.size();
  LOG(INFO) << "Summary: " << response.summary();
  return 0;
}

void OnApplicationInstalledCallback(
    base::RunLoop* run_loop,
    vm_tools::cicerone::InstallLinuxPackageProgressSignal::Status* final_status,
    std::string* failure_details,
    dbus::Signal* signal) {
  dbus::MessageReader reader(signal);
  vm_tools::cicerone::InstallLinuxPackageProgressSignal ilpps;
  if (!reader.PopArrayOfBytesAsProto(&ilpps)) {
    LOG(ERROR) << "Failed parsing InstallLinuxPackageProgressSignal proto";
    return;
  }

  if (ilpps.status() ==
      vm_tools::cicerone::InstallLinuxPackageProgressSignal::DOWNLOADING) {
    LOG(INFO) << "Downloading install packages, progress: "
              << ilpps.progress_percent();
    return;
  } else if (ilpps.status() ==
             vm_tools::cicerone::InstallLinuxPackageProgressSignal::
                 INSTALLING) {
    LOG(INFO) << "Installing packages, progress: " << ilpps.progress_percent();
    return;
  }

  *final_status = ilpps.status();
  *failure_details = ilpps.failure_details();
  run_loop->Quit();
}

int InstallLinuxPackage(dbus::ObjectProxy* proxy,
                        const string& vm_name,
                        const string& container_name,
                        const string& owner_id,
                        string file_path) {
  if (file_path.empty()) {
    LOG(ERROR) << "--file_path is required";
    return -1;
  }
  LOG(INFO) << "Installing Linux package";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kInstallLinuxPackageMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::InstallLinuxPackageRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);
  request.set_file_path(std::move(file_path));

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode InstallLinuxPackageRequest protobuf";
    return -1;
  }

  // RunLoop so we can monitor the D-Bus signals coming back to determine when
  // application install has actually finished.
  base::RunLoop run_loop;
  vm_tools::cicerone::InstallLinuxPackageProgressSignal::Status final_status =
      vm_tools::cicerone::InstallLinuxPackageProgressSignal::FAILED;
  std::string failure_details = "Timed out waiting for reply";
  proxy->ConnectToSignal(vm_tools::cicerone::kVmCiceroneInterface,
                         vm_tools::cicerone::kInstallLinuxPackageProgressSignal,
                         base::BindRepeating(&OnApplicationInstalledCallback,
                                             base::Unretained(&run_loop),
                                             &final_status, &failure_details),
                         base::BindOnce(&OnSignalConnected));

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::InstallLinuxPackageResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  switch (response.status()) {
    case vm_tools::cicerone::InstallLinuxPackageResponse::STARTED:
      LOG(INFO) << "Successfully started the package install";
      // Start the RunLoop which'll get the D-Bus signal callbacks and set the
      // final result for us.
      LOG(INFO) << "Waiting for D-Bus signal for application install status";
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMinutes(10));
      run_loop.Run();

      if (final_status ==
          vm_tools::cicerone::InstallLinuxPackageProgressSignal::SUCCEEDED) {
        LOG(INFO) << "Finished application install successfully";
        return 0;
      } else {
        LOG(ERROR) << "Failed to install application: " << failure_details;
        return -1;
      }
    case vm_tools::cicerone::InstallLinuxPackageResponse::
        INSTALL_ALREADY_ACTIVE:
      LOG(ERROR) << "Failed starting the package install because one is "
                    "already active";
      return -1;
    default:
      LOG(ERROR) << "Failed starting the package install, reason: "
                 << response.failure_reason();
      return -1;
  }
}

void OnApplicationUninstalledCallback(
    base::RunLoop* run_loop,
    vm_tools::cicerone::UninstallPackageProgressSignal::Status* final_status,
    std::string* failure_details,
    dbus::Signal* signal) {
  dbus::MessageReader reader(signal);
  vm_tools::cicerone::UninstallPackageProgressSignal progress_signal;
  if (!reader.PopArrayOfBytesAsProto(&progress_signal)) {
    LOG(ERROR) << "Failed parsing UninstallPackageProgressSignal proto";
    return;
  }

  if (progress_signal.status() ==
      vm_tools::cicerone::UninstallPackageProgressSignal::UNINSTALLING) {
    LOG(INFO) << "Uninstall packages, progress: "
              << progress_signal.progress_percent();
    return;
  }

  *final_status = progress_signal.status();
  *failure_details = progress_signal.failure_details();
  run_loop->Quit();
}

int UninstallApplication(dbus::ObjectProxy* proxy,
                         const string& vm_name,
                         const string& container_name,
                         const string& owner_id,
                         const string& application) {
  if (application.empty()) {
    LOG(ERROR) << "--application is required";
    return -1;
  }
  LOG(INFO) << "Uninstalling application";

  dbus::MethodCall method_call(
      vm_tools::cicerone::kVmCiceroneInterface,
      vm_tools::cicerone::kUninstallPackageOwningFileMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::UninstallPackageOwningFileRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);
  request.set_desktop_file_id(application);

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode UninstallPackageOwningFileRequest protobuf";
    return -1;
  }

  // RunLoop so we can monitor the D-Bus signals coming back to determine when
  // application uninstall has actually finished.
  base::RunLoop run_loop;
  vm_tools::cicerone::UninstallPackageProgressSignal::Status final_status =
      vm_tools::cicerone::UninstallPackageProgressSignal::FAILED;
  std::string failure_details = "Timed out waiting for reply";
  proxy->ConnectToSignal(vm_tools::cicerone::kVmCiceroneInterface,
                         vm_tools::cicerone::kUninstallPackageProgressSignal,
                         base::BindRepeating(&OnApplicationUninstalledCallback,
                                             base::Unretained(&run_loop),
                                             &final_status, &failure_details),
                         base::BindOnce(&OnSignalConnected));

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::UninstallPackageOwningFileResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  switch (response.status()) {
    case vm_tools::cicerone::UninstallPackageOwningFileResponse::STARTED:
      LOG(INFO) << "Successfully started the package uninstall";
      // Start the RunLoop which'll get the D-Bus signal callbacks and set the
      // final result for us.
      LOG(INFO) << "Waiting for D-Bus signal for application uninstall status";
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMinutes(10));
      run_loop.Run();

      if (final_status ==
          vm_tools::cicerone::UninstallPackageProgressSignal::SUCCEEDED) {
        LOG(INFO) << "Finished application uninstall successfully";
        return 0;
      } else {
        LOG(ERROR) << "Failed to uninstall application: " << failure_details;
        return -1;
      }
    case vm_tools::cicerone::UninstallPackageOwningFileResponse::
        BLOCKING_OPERATION_IN_PROGRESS:
      LOG(ERROR) << "Failed starting the package uninstall because one is "
                    "already active";
      return -1;
    default:
      LOG(ERROR) << "Failed starting the package uninstall, reason: "
                 << response.failure_reason();
      return -1;
  }
}

void OnPlaybookAppliedCallback(
    base::RunLoop* run_loop,
    vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::Status*
        final_status,
    std::string* failure_details,
    dbus::Signal* signal) {
  dbus::MessageReader reader(signal);
  vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal progress_signal;
  if (!reader.PopArrayOfBytesAsProto(&progress_signal)) {
    LOG(ERROR) << "Failed parsing ApplyAnsiblePlaybookProgressSignal proto";
    return;
  }

  if (progress_signal.status() ==
      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::IN_PROGRESS) {
    LOG(INFO) << "Applying playbook...";
    return;
  }

  *final_status = progress_signal.status();
  *failure_details = progress_signal.failure_details();
  run_loop->Quit();
}

int ApplyAnsiblePlaybook(dbus::ObjectProxy* proxy,
                         const string& vm_name,
                         const string& container_name,
                         const string& owner_id,
                         string playbook) {
  if (playbook.empty()) {
    LOG(ERROR) << "--playbook is required";
    return -1;
  }
  LOG(INFO) << "Applying Ansible playbook";

  dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
                               vm_tools::cicerone::kApplyAnsiblePlaybookMethod);
  dbus::MessageWriter writer(&method_call);

  vm_tools::cicerone::ApplyAnsiblePlaybookRequest request;
  request.set_vm_name(vm_name);
  request.set_container_name(container_name);
  request.set_owner_id(owner_id);
  request.set_playbook(std::move(playbook));

  if (!writer.AppendProtoAsArrayOfBytes(request)) {
    LOG(ERROR) << "Failed to encode ApplyAnsiblePlaybookRequest protobuf";
    return -1;
  }

  // RunLoop so we can monitor the D-Bus signals coming back to determine when
  // playbook application has actually finished.
  base::RunLoop run_loop;
  vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::Status final_status =
      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED;
  std::string failure_details = "Timed out waiting for reply";
  proxy->ConnectToSignal(
      vm_tools::cicerone::kVmCiceroneInterface,
      vm_tools::cicerone::kApplyAnsiblePlaybookProgressSignal,
      base::BindRepeating(&OnPlaybookAppliedCallback,
                          base::Unretained(&run_loop), &final_status,
                          &failure_details),
      base::BindOnce(&OnSignalConnected));

  std::unique_ptr<dbus::Response> dbus_response =
      proxy->CallMethodAndBlock(&method_call, kDefaultTimeoutMs);
  if (!dbus_response) {
    LOG(ERROR) << "Failed to send dbus message to cicerone service";
    return -1;
  }

  dbus::MessageReader reader(dbus_response.get());
  vm_tools::cicerone::ApplyAnsiblePlaybookResponse response;
  if (!reader.PopArrayOfBytesAsProto(&response)) {
    LOG(ERROR) << "Failed to parse response protobuf";
    return -1;
  }
  switch (response.status()) {
    case vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED:
      LOG(INFO) << "Successfully started the playbook application";
      // Start the RunLoop which'll get the D-Bus signal callbacks and set the
      // final result for us.
      LOG(INFO) << "Waiting for D-Bus signal for playbook application status";
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMinutes(10));
      run_loop.Run();

      if (final_status ==
          vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED) {
        LOG(INFO) << "Finished playbook application successfully";
        return 0;
      }
      LOG(ERROR) << "Failed to apply playbook: " << failure_details;
      return -1;
    case vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED:
      LOG(ERROR) << "Failed starting the playbook application, reason: "
                 << response.failure_reason();
      return -1;
    default:
      NOTREACHED();
      return -1;
  }
}

}  // namespace

int main(int argc, char** argv) {
  base::AtExitManager at_exit;

  // Operations.
  DEFINE_bool(create_lxd_container, false, "Create an LXD container");
  DEFINE_bool(start_lxd_container, false, "Start an LXD container");
  DEFINE_bool(set_timezone, false, "Set timezone for all known LXD containers");
  DEFINE_bool(get_username, false, "Get the primary username in a container");
  DEFINE_bool(set_up_lxd_user, false, "Set up a user in an LXD container");
  DEFINE_bool(launch_application, false,
              "Launches an application in a container");
  DEFINE_bool(get_icon, false, "Get an app icon from a container within a VM");
  DEFINE_bool(get_info, false, "Get debug information about all running VMs");
  DEFINE_bool(install_package, false, "Install a Linux package file");
  DEFINE_bool(uninstall_application, false, "Uninstall an application");
  DEFINE_bool(package_info, false, "Gets information on a Linux package file");
  DEFINE_bool(apply_playbook, false, "Apply an Ansible playbook");

  // Parameters.
  DEFINE_string(vm_name, "", "VM name");
  DEFINE_string(container_name, "", "Container name");
  DEFINE_string(owner_id, "", "User id");
  DEFINE_string(image_server, "", "Image server to pull a container from");
  DEFINE_string(image_alias, "", "Container image alias");
  DEFINE_string(rootfs_path, "", "Path to rootfs tarball");
  DEFINE_string(metadata_path, "", "Path to metadata tarball");
  DEFINE_string(container_username, "", "Container username");
  DEFINE_string(application, "", "Name of the application to launch");
  DEFINE_string(output_filepath, "",
                "Filename with path to write appliction icon to");
  DEFINE_string(timezone_name, "",
                "The timezone to set, for example 'America/Denver'. "
                "See /usr/share/zoneinfo for other valid names.");
  DEFINE_int32(icon_size, 48,
               "The size of the icon to get is this icon_size by icon_size");
  DEFINE_int32(scale, 1, "The scale that the icon is designed to use with");
  DEFINE_string(file_path, "", "Package file path");
  DEFINE_string(playbook, "", "Ansible playbook content");

  brillo::FlagHelper::Init(argc, argv, "vm_cicerone client tool");
  brillo::InitLog(brillo::kLogToStderrIfTty);

  base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::IO);
  base::FileDescriptorWatcher watcher(task_executor.task_runner());

  dbus::Bus::Options opts;
  opts.bus_type = dbus::Bus::SYSTEM;
  scoped_refptr<dbus::Bus> bus(new dbus::Bus(std::move(opts)));

  if (!bus->Connect()) {
    LOG(ERROR) << "Failed to connect to system bus";
    return -1;
  }

  dbus::ObjectProxy* proxy = bus->GetObjectProxy(
      vm_tools::cicerone::kVmCiceroneServiceName,
      dbus::ObjectPath(vm_tools::cicerone::kVmCiceroneServicePath));
  if (!proxy) {
    LOG(ERROR) << "Unable to get dbus proxy for "
               << vm_tools::cicerone::kVmCiceroneServiceName;
    return -1;
  }

  // The standard says that bool to int conversion is implicit and that
  // false => 0 and true => 1.
  // clang-format off
  if (FLAGS_create_lxd_container + FLAGS_start_lxd_container +
      FLAGS_set_timezone + FLAGS_set_up_lxd_user + FLAGS_get_username +
      FLAGS_launch_application + FLAGS_get_icon + FLAGS_get_info +
      FLAGS_install_package + FLAGS_uninstall_application +
      FLAGS_package_info + FLAGS_apply_playbook != 1) {
    // clang-format on
    LOG(ERROR) << "Exactly one of --create_lxd_container, "
               << "--start_lxd_container, --set_up_lxd_user, --set_timezone, "
               << "--get_username, --launch_application, --get_icon, "
               << "--get_info, --install_package, --uninstall_application, "
               << "--apply_playbook, or --package_info must be provided";
    return -1;
  }

  // Check for the get_info and set_timezone commands early because they do
  // not require owner ID, VM name, or container name.
  if (FLAGS_get_info) {
    return GetInfo(proxy);
  }

  if (FLAGS_set_timezone) {
    return SetTimezone(proxy, FLAGS_timezone_name);
  }

  // Every other D-Bus method for cicerone requires owner ID, VM name, and
  // container name.
  if (FLAGS_owner_id.empty()) {
    LOG(ERROR) << "--owner_id is required";
    return -1;
  }

  if (FLAGS_vm_name.empty()) {
    LOG(ERROR) << "--vm_name is required";
    return -1;
  }

  if (FLAGS_container_name.empty()) {
    LOG(ERROR) << "--container_name is required";
    return -1;
  }

  if (FLAGS_create_lxd_container) {
    return CreateLxdContainer(
        proxy, FLAGS_vm_name, FLAGS_container_name, FLAGS_owner_id,
        std::move(FLAGS_image_server), std::move(FLAGS_image_alias),
        std::move(FLAGS_rootfs_path), std::move(FLAGS_metadata_path));
  } else if (FLAGS_start_lxd_container) {
    return StartLxdContainer(proxy, FLAGS_vm_name, FLAGS_container_name,
                             FLAGS_owner_id);
  } else if (FLAGS_set_up_lxd_user) {
    return SetUpLxdContainerUser(proxy, FLAGS_vm_name, FLAGS_container_name,
                                 FLAGS_owner_id,
                                 std::move(FLAGS_container_username));
  } else if (FLAGS_get_username) {
    return GetLxdContainerUsername(proxy, FLAGS_vm_name, FLAGS_container_name,
                                   FLAGS_owner_id);
  } else if (FLAGS_launch_application) {
    return LaunchApplication(
        proxy, std::move(FLAGS_owner_id), std::move(FLAGS_vm_name),
        std::move(FLAGS_container_name), std::move(FLAGS_application));
  } else if (FLAGS_get_icon) {
    return GetIcon(proxy, std::move(FLAGS_owner_id), std::move(FLAGS_vm_name),
                   std::move(FLAGS_container_name),
                   std::move(FLAGS_application), FLAGS_icon_size, FLAGS_scale,
                   std::move(FLAGS_output_filepath));
  } else if (FLAGS_install_package) {
    return InstallLinuxPackage(proxy, FLAGS_vm_name, FLAGS_container_name,
                               FLAGS_owner_id, std::move(FLAGS_file_path));
  } else if (FLAGS_uninstall_application) {
    return UninstallApplication(proxy, FLAGS_vm_name, FLAGS_container_name,
                                FLAGS_owner_id, FLAGS_application);
  } else if (FLAGS_package_info) {
    return GetLinuxPackageInfo(proxy, FLAGS_vm_name, FLAGS_container_name,
                               FLAGS_owner_id, std::move(FLAGS_file_path));
  } else if (FLAGS_apply_playbook) {
    return ApplyAnsiblePlaybook(proxy, FLAGS_vm_name, FLAGS_container_name,
                                FLAGS_owner_id, std::move(FLAGS_playbook));
  }

  // Unreachable.
  return 0;
}
