// 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 <string>

#include <base/command_line.h>
#include <base/logging.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/flag_helper.h>
#include <dbus/dbus.h>
#include <glib.h>
#include <inttypes.h>

#include "update_engine/dbus_constants.h"
#include "update_engine/glib_utils.h"

extern "C" {
#include "update_engine/update_engine.dbusclient.h"
}

using chromeos_update_engine::AttemptUpdateFlags;
using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
using chromeos_update_engine::kUpdateEngineServiceInterface;
using chromeos_update_engine::kUpdateEngineServiceName;
using chromeos_update_engine::kUpdateEngineServicePath;
using chromeos_update_engine::utils::GetAndFreeGError;
using std::string;

namespace {

bool GetProxy(DBusGProxy** out_proxy) {
  DBusGConnection* bus;
  DBusGProxy* proxy = nullptr;
  GError* error = nullptr;
  const int kTries = 4;
  const int kRetrySeconds = 10;

  bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
  if (bus == nullptr) {
    LOG(ERROR) << "Failed to get bus: " << GetAndFreeGError(&error);
    exit(1);
  }
  for (int i = 0; !proxy && i < kTries; ++i) {
    if (i > 0) {
      LOG(INFO) << "Retrying to get dbus proxy. Try "
                << (i + 1) << "/" << kTries;
      g_usleep(kRetrySeconds * G_USEC_PER_SEC);
    }
    proxy = dbus_g_proxy_new_for_name_owner(bus,
                                            kUpdateEngineServiceName,
                                            kUpdateEngineServicePath,
                                            kUpdateEngineServiceInterface,
                                            &error);
    LOG_IF(WARNING, !proxy) << "Error getting dbus proxy for "
                            << kUpdateEngineServiceName << ": "
                            << GetAndFreeGError(&error);
  }
  if (proxy == nullptr) {
    LOG(ERROR) << "Giving up -- unable to get dbus proxy for "
               << kUpdateEngineServiceName;
    exit(1);
  }
  *out_proxy = proxy;
  return true;
}

static void StatusUpdateSignalHandler(DBusGProxy* proxy,
                                      int64_t last_checked_time,
                                      double progress,
                                      gchar* current_operation,
                                      gchar* new_version,
                                      int64_t new_size,
                                      void* user_data) {
  LOG(INFO) << "Got status update:";
  LOG(INFO) << "  last_checked_time: " << last_checked_time;
  LOG(INFO) << "  progress: " << progress;
  LOG(INFO) << "  current_operation: " << current_operation;
  LOG(INFO) << "  new_version: " << new_version;
  LOG(INFO) << "  new_size: " << new_size;
}

bool ResetStatus() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean rc = update_engine_client_reset_status(proxy, &error);
  return rc;
}


// If |op| is non-null, sets it to the current operation string or an
// empty string if unable to obtain the current status.
bool GetStatus(string* op) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gint64 last_checked_time = 0;
  gdouble progress = 0.0;
  char* current_op = nullptr;
  char* new_version = nullptr;
  gint64 new_size = 0;

  gboolean rc = update_engine_client_get_status(proxy,
                                                &last_checked_time,
                                                &progress,
                                                &current_op,
                                                &new_version,
                                                &new_size,
                                                &error);
  if (rc == FALSE) {
    LOG(INFO) << "Error getting status: " << GetAndFreeGError(&error);
  }
  printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n"
         "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n",
         last_checked_time,
         progress,
         current_op,
         new_version,
         new_size);
  if (op) {
    *op = current_op ? current_op : "";
  }
  return true;
}

// Should never return.
void WatchForUpdates() {
  DBusGProxy* proxy;

  CHECK(GetProxy(&proxy));

  // Register marshaller
  dbus_g_object_register_marshaller(
      g_cclosure_marshal_generic,
      G_TYPE_NONE,
      G_TYPE_INT64,
      G_TYPE_DOUBLE,
      G_TYPE_STRING,
      G_TYPE_STRING,
      G_TYPE_INT64,
      G_TYPE_INVALID);

  static const char kStatusUpdate[] = "StatusUpdate";
  dbus_g_proxy_add_signal(proxy,
                          kStatusUpdate,
                          G_TYPE_INT64,
                          G_TYPE_DOUBLE,
                          G_TYPE_STRING,
                          G_TYPE_STRING,
                          G_TYPE_INT64,
                          G_TYPE_INVALID);
  GMainLoop* loop = g_main_loop_new(nullptr, TRUE);
  dbus_g_proxy_connect_signal(proxy,
                              kStatusUpdate,
                              G_CALLBACK(StatusUpdateSignalHandler),
                              nullptr,
                              nullptr);
  g_main_loop_run(loop);
  g_main_loop_unref(loop);
}

bool Rollback(bool rollback) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean rc = update_engine_client_attempt_rollback(proxy,
                                                      rollback,
                                                      &error);
  CHECK_EQ(rc, TRUE) << "Error with rollback request: "
                     << GetAndFreeGError(&error);
  return true;
}

string GetRollbackPartition() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  char* rollback_partition = nullptr;
  gboolean rc = update_engine_client_get_rollback_partition(proxy,
                                                            &rollback_partition,
                                                            &error);
  CHECK_EQ(rc, TRUE) << "Error while querying rollback partition availabilty: "
                     << GetAndFreeGError(&error);
  string partition = rollback_partition;
  g_free(rollback_partition);
  return partition;
}

string GetKernelDevices() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  char* kernel_devices = nullptr;
  gboolean rc = update_engine_client_get_kernel_devices(proxy,
                                                        &kernel_devices,
                                                        &error);
  CHECK_EQ(rc, TRUE) << "Error while getting a list of kernel devices: "
    << GetAndFreeGError(&error);
  string devices = kernel_devices;
  g_free(kernel_devices);
  return devices;
}

bool CheckForUpdates(const string& app_version,
                     const string& omaha_url,
                     bool interactive) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(
      interactive ? 0 : kAttemptUpdateFlagNonInteractive);
  gboolean rc =
      update_engine_client_attempt_update_with_flags(proxy,
                                                     app_version.c_str(),
                                                     omaha_url.c_str(),
                                                     static_cast<gint>(flags),
                                                     &error);
  CHECK_EQ(rc, TRUE) << "Error checking for update: "
                     << GetAndFreeGError(&error);
  return true;
}

bool RebootIfNeeded() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean rc =
      update_engine_client_reboot_if_needed(proxy, &error);
  // Reboot error code doesn't necessarily mean that a reboot
  // failed. For example, D-Bus may be shutdown before we receive the
  // result.
  LOG_IF(INFO, !rc) << "Reboot error message: " << GetAndFreeGError(&error);
  return true;
}

void SetTargetChannel(const string& target_channel, bool allow_powerwash) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean rc = update_engine_client_set_channel(proxy,
                                                 target_channel.c_str(),
                                                 allow_powerwash,
                                                 &error);
  CHECK_EQ(rc, true) << "Error setting the channel: "
                     << GetAndFreeGError(&error);
  LOG(INFO) << "Channel permanently set to: " << target_channel;
}

string GetChannel(bool get_current_channel) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  char* channel = nullptr;
  gboolean rc = update_engine_client_get_channel(proxy,
                                                 get_current_channel,
                                                 &channel,
                                                 &error);
  CHECK_EQ(rc, true) << "Error getting the channel: "
                     << GetAndFreeGError(&error);
  string output = channel;
  g_free(channel);
  return output;
}

void SetUpdateOverCellularPermission(gboolean allowed) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean rc = update_engine_client_set_update_over_cellular_permission(
      proxy,
      allowed,
      &error);
  CHECK_EQ(rc, true) << "Error setting the update over cellular setting: "
                     << GetAndFreeGError(&error);
}

bool GetUpdateOverCellularPermission() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean allowed;
  gboolean rc = update_engine_client_get_update_over_cellular_permission(
      proxy,
      &allowed,
      &error);
  CHECK_EQ(rc, true) << "Error getting the update over cellular setting: "
                     << GetAndFreeGError(&error);
  return allowed;
}

void SetP2PUpdatePermission(gboolean enabled) {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean rc = update_engine_client_set_p2p_update_permission(
      proxy,
      enabled,
      &error);
  CHECK_EQ(rc, true) << "Error setting the peer-to-peer update setting: "
                     << GetAndFreeGError(&error);
}

bool GetP2PUpdatePermission() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  gboolean enabled;
  gboolean rc = update_engine_client_get_p2p_update_permission(
      proxy,
      &enabled,
      &error);
  CHECK_EQ(rc, true) << "Error getting the peer-to-peer update setting: "
                     << GetAndFreeGError(&error);
  return enabled;
}

static gboolean CompleteUpdateSource(gpointer data) {
  string current_op;
  if (!GetStatus(&current_op) || current_op == "UPDATE_STATUS_IDLE") {
    LOG(ERROR) << "Update failed.";
    exit(1);
  }
  if (current_op == "UPDATE_STATUS_UPDATED_NEED_REBOOT") {
    LOG(INFO) << "Update succeeded -- reboot needed.";
    exit(0);
  }
  return TRUE;
}

// This is similar to watching for updates but rather than registering
// a signal watch, actively poll the daemon just in case it stops
// sending notifications.
void CompleteUpdate() {
  GMainLoop* loop = g_main_loop_new(nullptr, TRUE);
  g_timeout_add_seconds(5, CompleteUpdateSource, nullptr);
  g_main_loop_run(loop);
  g_main_loop_unref(loop);
}

void ShowPrevVersion() {
  DBusGProxy* proxy;
  GError* error = nullptr;

  CHECK(GetProxy(&proxy));

  char* prev_version = nullptr;

  gboolean rc = update_engine_client_get_prev_version(proxy,
                                                      &prev_version,
                                                      &error);
  if (!rc) {
    LOG(ERROR) << "Error getting previous version: "
               << GetAndFreeGError(&error);
  } else {
    LOG(INFO) << "Previous version = " << prev_version;
    g_free(prev_version);
  }
}

bool CheckIfRebootIsNeeded(DBusGProxy *proxy, bool *out_reboot_needed) {
  gint64 last_checked_time = 0;
  gdouble progress = 0.0;
  char* current_op = nullptr;
  char* new_version = nullptr;
  gint64 new_size = 0;
  GError* error = nullptr;

  if (!update_engine_client_get_status(proxy,
                                       &last_checked_time,
                                       &progress,
                                       &current_op,
                                       &new_version,
                                       &new_size,
                                       &error)) {
    LOG(INFO) << "Error getting status: " << GetAndFreeGError(&error);
    return false;
  }
  *out_reboot_needed =
      (g_strcmp0(current_op,
                 update_engine::kUpdateStatusUpdatedNeedReboot) == 0);
  g_free(current_op);
  g_free(new_version);
  return true;
}

// Determines if reboot is needed. The result is returned in
// |out_reboot_needed|. Returns true if the check succeeded, false
// otherwise.
bool IsRebootNeeded(bool *out_reboot_needed) {
  DBusGProxy* proxy = nullptr;
  CHECK(GetProxy(&proxy));
  bool ret = CheckIfRebootIsNeeded(proxy, out_reboot_needed);
  g_object_unref(proxy);
  return ret;
}

static void OnBlockUntilRebootStatusCallback(
    DBusGProxy* proxy,
    int64_t last_checked_time,
    double progress,
    const gchar* current_operation,
    const gchar* new_version,
    int64_t new_size,
    void* user_data) {
  GMainLoop *loop = reinterpret_cast<GMainLoop*>(user_data);
  if (g_strcmp0(current_operation,
                update_engine::kUpdateStatusUpdatedNeedReboot) == 0) {
    g_main_loop_quit(loop);
  }
}

bool CheckRebootNeeded(DBusGProxy *proxy, GMainLoop *loop) {
  bool reboot_needed;
  if (!CheckIfRebootIsNeeded(proxy, &reboot_needed))
    return false;
  if (reboot_needed)
    return true;
  // This will block until OnBlockUntilRebootStatusCallback() calls
  // g_main_loop_quit().
  g_main_loop_run(loop);
  return true;
}

// Blocks until a reboot is needed. Returns true if waiting succeeded,
// false if an error occurred.
bool BlockUntilRebootIsNeeded() {
  // The basic idea is to get a proxy, listen to signals and only then
  // check the status. If no reboot is needed, just sit and wait for
  // the StatusUpdate signal to convey that a reboot is pending.
  DBusGProxy* proxy = nullptr;
  CHECK(GetProxy(&proxy));
  dbus_g_object_register_marshaller(
      g_cclosure_marshal_generic,
      G_TYPE_NONE,
      G_TYPE_INT64,
      G_TYPE_DOUBLE,
      G_TYPE_STRING,
      G_TYPE_STRING,
      G_TYPE_INT64,
      G_TYPE_INVALID);
  dbus_g_proxy_add_signal(proxy,
                          update_engine::kStatusUpdate,  // Signal name.
                          G_TYPE_INT64,
                          G_TYPE_DOUBLE,
                          G_TYPE_STRING,
                          G_TYPE_STRING,
                          G_TYPE_INT64,
                          G_TYPE_INVALID);
  GMainLoop* loop = g_main_loop_new(nullptr, TRUE);
  dbus_g_proxy_connect_signal(proxy,
                              update_engine::kStatusUpdate,
                              G_CALLBACK(OnBlockUntilRebootStatusCallback),
                              loop,
                              nullptr);  // free_data_func.

  bool ret = CheckRebootNeeded(proxy, loop);

  dbus_g_proxy_disconnect_signal(proxy,
                                 update_engine::kStatusUpdate,
                                 G_CALLBACK(OnBlockUntilRebootStatusCallback),
                                 loop);
  g_main_loop_unref(loop);
  g_object_unref(proxy);
  return ret;
}

}  // namespace

int main(int argc, char** argv) {
  DEFINE_string(app_version, "", "Force the current app version.");
  DEFINE_string(channel, "",
                "Set the target channel. The device will be powerwashed if the "
                "target channel is more stable than the current channel unless "
                "--nopowerwash is specified.");
  DEFINE_bool(check_for_update, false, "Initiate check for updates.");
  DEFINE_bool(follow, false, "Wait for any update operations to complete."
              "Exit status is 0 if the update succeeded, and 1 otherwise.");
  DEFINE_bool(interactive, true, "Mark the update request as interactive.");
  DEFINE_string(omaha_url, "", "The URL of the Omaha update server.");
  DEFINE_string(p2p_update, "",
                "Enables (\"yes\") or disables (\"no\") the peer-to-peer update"
                " sharing.");
  DEFINE_bool(powerwash, true, "When performing rollback or channel change, "
              "do a powerwash or allow it respectively.");
  DEFINE_bool(reboot, false, "Initiate a reboot if needed.");
  DEFINE_bool(is_reboot_needed, false, "Exit status 0 if reboot is needed, "
              "2 if reboot is not needed or 1 if an error occurred.");
  DEFINE_bool(block_until_reboot_is_needed, false, "Blocks until reboot is "
              "needed. Returns non-zero exit status if an error occurred.");
  DEFINE_bool(reset_status, false, "Sets the status in update_engine to idle.");
  DEFINE_bool(rollback, false,
              "Perform a rollback to the previous partition. The device will "
              "be powerwashed unless --nopowerwash is specified.");
  DEFINE_bool(can_rollback, false, "Shows whether rollback partition "
              "is available.");
  DEFINE_bool(show_channel, false, "Show the current and target channels.");
  DEFINE_bool(show_p2p_update, false,
              "Show the current setting for peer-to-peer update sharing.");
  DEFINE_bool(show_update_over_cellular, false,
              "Show the current setting for updates over cellular networks.");
  DEFINE_bool(status, false, "Print the status to stdout.");
  DEFINE_bool(update, false, "Forces an update and waits for it to complete. "
              "Implies --follow.");
  DEFINE_string(update_over_cellular, "",
                "Enables (\"yes\") or disables (\"no\") the updates over "
                "cellular networks.");
  DEFINE_bool(watch_for_updates, false,
              "Listen for status updates and print them to the screen.");
  DEFINE_bool(prev_version, false,
              "Show the previous OS version used before the update reboot.");
  DEFINE_bool(show_kernels, false, "Show the list of kernel patritions and "
              "whether each of them is bootable or not");

  // Boilerplate init commands.
  g_type_init();
  dbus_threads_init_default();
  chromeos::FlagHelper::Init(argc, argv, "Chromium OS Update Engine Client");

  // Ensure there are no positional arguments.
  const std::vector<string> positional_args =
      base::CommandLine::ForCurrentProcess()->GetArgs();
  if (!positional_args.empty()) {
    LOG(ERROR) << "Found a positional argument '" << positional_args.front()
               << "'. If you want to pass a value to a flag, pass it as "
                  "--flag=value.";
    return 1;
  }

  // Update the status if requested.
  if (FLAGS_reset_status) {
    LOG(INFO) << "Setting Update Engine status to idle ...";
    if (!ResetStatus()) {
      LOG(ERROR) << "ResetStatus failed.";
      return 1;
    }
    LOG(INFO) << "ResetStatus succeeded; to undo partition table changes run:\n"
                 "(D=$(rootdev -d) P=$(rootdev -s); cgpt p -i$(($(echo ${P#$D} "
                 "| sed 's/^[^0-9]*//')-1)) $D;)";
  }

  // Changes the current update over cellular network setting.
  if (!FLAGS_update_over_cellular.empty()) {
    gboolean allowed = FLAGS_update_over_cellular == "yes";
    if (!allowed && FLAGS_update_over_cellular != "no") {
      LOG(ERROR) << "Unknown option: \"" << FLAGS_update_over_cellular
                 << "\". Please specify \"yes\" or \"no\".";
    } else {
      SetUpdateOverCellularPermission(allowed);
    }
  }

  // Show the current update over cellular network setting.
  if (FLAGS_show_update_over_cellular) {
    bool allowed = GetUpdateOverCellularPermission();
    LOG(INFO) << "Current update over cellular network setting: "
              << (allowed ? "ENABLED" : "DISABLED");
  }

  if (!FLAGS_powerwash && !FLAGS_rollback && FLAGS_channel.empty()) {
    LOG(ERROR) << "powerwash flag only makes sense rollback or channel change";
    return 1;
  }

  // Change the P2P enabled setting.
  if (!FLAGS_p2p_update.empty()) {
    gboolean enabled = FLAGS_p2p_update == "yes";
    if (!enabled && FLAGS_p2p_update != "no") {
      LOG(ERROR) << "Unknown option: \"" << FLAGS_p2p_update
                 << "\". Please specify \"yes\" or \"no\".";
    } else {
      SetP2PUpdatePermission(enabled);
    }
  }

  // Show the rollback availability.
  if (FLAGS_can_rollback) {
    string rollback_partition = GetRollbackPartition();
    bool can_rollback = true;
    if (rollback_partition.empty()) {
      rollback_partition = "UNAVAILABLE";
      can_rollback = false;
    } else {
      rollback_partition = "AVAILABLE: " + rollback_partition;
    }

    LOG(INFO) << "Rollback partition: " << rollback_partition;
    if (!can_rollback) {
      return 1;
    }
  }

  // Show the current P2P enabled setting.
  if (FLAGS_show_p2p_update) {
    bool enabled = GetP2PUpdatePermission();
    LOG(INFO) << "Current update using P2P setting: "
              << (enabled ? "ENABLED" : "DISABLED");
  }

  // First, update the target channel if requested.
  if (!FLAGS_channel.empty())
    SetTargetChannel(FLAGS_channel, FLAGS_powerwash);

  // Show the current and target channels if requested.
  if (FLAGS_show_channel) {
    string current_channel = GetChannel(true);
    LOG(INFO) << "Current Channel: " << current_channel;

    string target_channel = GetChannel(false);
    if (!target_channel.empty())
      LOG(INFO) << "Target Channel (pending update): " << target_channel;
  }

  bool do_update_request = FLAGS_check_for_update | FLAGS_update |
      !FLAGS_app_version.empty() | !FLAGS_omaha_url.empty();
  if (FLAGS_update)
    FLAGS_follow = true;

  if (do_update_request && FLAGS_rollback) {
    LOG(ERROR) << "Incompatible flags specified with rollback."
               << "Rollback should not include update-related flags.";
    return 1;
  }

  if (FLAGS_rollback) {
    LOG(INFO) << "Requesting rollback.";
    CHECK(Rollback(FLAGS_powerwash)) << "Request for rollback failed.";
  }

  // Initiate an update check, if necessary.
  if (do_update_request) {
    LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored.";
    string app_version = FLAGS_app_version;
    if (FLAGS_update && app_version.empty()) {
      app_version = "ForcedUpdate";
      LOG(INFO) << "Forcing an update by setting app_version to ForcedUpdate.";
    }
    LOG(INFO) << "Initiating update check and install.";
    CHECK(CheckForUpdates(app_version, FLAGS_omaha_url, FLAGS_interactive))
        << "Update check/initiate update failed.";
  }

  // These final options are all mutually exclusive with one another.
  if (FLAGS_follow + FLAGS_watch_for_updates + FLAGS_reboot +
      FLAGS_status + FLAGS_is_reboot_needed +
      FLAGS_block_until_reboot_is_needed > 1) {
    LOG(ERROR) << "Multiple exclusive options selected. "
               << "Select only one of --follow, --watch_for_updates, --reboot, "
               << "--is_reboot_needed, --block_until_reboot_is_needed, "
               << "or --status.";
    return 1;
  }

  if (FLAGS_status) {
    LOG(INFO) << "Querying Update Engine status...";
    if (!GetStatus(nullptr)) {
      LOG(ERROR) << "GetStatus failed.";
      return 1;
    }
    return 0;
  }

  if (FLAGS_follow) {
    LOG(INFO) << "Waiting for update to complete.";
    CompleteUpdate();  // Should never return.
    return 1;
  }

  if (FLAGS_watch_for_updates) {
    LOG(INFO) << "Watching for status updates.";
    WatchForUpdates();  // Should never return.
    return 1;
  }

  if (FLAGS_reboot) {
    LOG(INFO) << "Requesting a reboot...";
    CHECK(RebootIfNeeded());
    return 0;
  }

  if (FLAGS_prev_version) {
    ShowPrevVersion();
  }

  if (FLAGS_show_kernels) {
    LOG(INFO) << "Kernel partitions:\n"
              << GetKernelDevices();
  }

  if (FLAGS_is_reboot_needed) {
    bool reboot_needed = false;
    if (!IsRebootNeeded(&reboot_needed))
      return 1;
    else if (!reboot_needed)
      return 2;
  }

  if (FLAGS_block_until_reboot_is_needed) {
    if (!BlockUntilRebootIsNeeded())
      return 1;
  }

  LOG(INFO) << "Done.";
  return 0;
}
