// 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 "update_engine/dbus_service.h"

#include <string>

#include <base/logging.h>

#include "update_engine/marshal.glibmarshal.h"
#include "update_engine/omaha_request_params.h"
#include "update_engine/utils.h"

using std::string;

static const char kAUTestURLRequest[] = "autest";
// By default autest bypasses scattering. If we want to test scattering,
// we should use autest-scheduled. The Url used is same in both cases, but
// different params are passed to CheckForUpdate method.
static const char kScheduledAUTestURLRequest[] = "autest-scheduled";

static const char kAUTestURL[] =
    "https://omaha.sandbox.google.com/service/update2";

G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT)

static void update_engine_service_finalize(GObject* object) {
  G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object);
}

static guint status_update_signal = 0;

static void update_engine_service_class_init(UpdateEngineServiceClass* klass) {
  GObjectClass *object_class;
  object_class = G_OBJECT_CLASS(klass);
  object_class->finalize = update_engine_service_finalize;

  status_update_signal = g_signal_new(
      "status_update",
      G_OBJECT_CLASS_TYPE(klass),
      G_SIGNAL_RUN_LAST,
      0,  // 0 == no class method associated
      NULL,  // Accumulator
      NULL,  // Accumulator data
      update_engine_VOID__INT64_DOUBLE_STRING_STRING_INT64,
      G_TYPE_NONE,  // Return type
      5,  // param count:
      G_TYPE_INT64,
      G_TYPE_DOUBLE,
      G_TYPE_STRING,
      G_TYPE_STRING,
      G_TYPE_INT64);
}

static void update_engine_service_init(UpdateEngineService* object) {
}

UpdateEngineService* update_engine_service_new(void) {
  return reinterpret_cast<UpdateEngineService*>(
      g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL));
}

gboolean update_engine_service_attempt_update(UpdateEngineService* self,
                                              gchar* app_version,
                                              gchar* omaha_url,
                                              GError **error) {
  string update_app_version;
  string update_omaha_url;
  bool is_user_initiated = true;

  // Only non-official (e.g., dev and test) builds can override the current
  // version and update server URL over D-Bus. However, pointing to the
  // hardcoded test update server URL is always allowed.
  if (!chromeos_update_engine::utils::IsOfficialBuild()) {
    if (app_version) {
      update_app_version = app_version;
    }
    if (omaha_url) {
      update_omaha_url = omaha_url;
    }
  }
  if (omaha_url) {
    if (strcmp(omaha_url, kScheduledAUTestURLRequest) == 0) {
      update_omaha_url = kAUTestURL;
      // pretend that it's not user-initiated even though it is,
      // so as to test scattering logic, etc. which get kicked off
      // only in scheduled update checks.
      is_user_initiated = false;
    } else if (strcmp(omaha_url, kAUTestURLRequest) == 0) {
      update_omaha_url = kAUTestURL;
    }
  }
  LOG(INFO) << "Attempt update: app_version=\"" << update_app_version << "\" "
            << "omaha_url=\"" << update_omaha_url << "\" "
            << "is_user_initiated=" << (is_user_initiated? "yes" : "no");
  self->update_attempter_->CheckForUpdate(update_app_version,
                                          update_omaha_url,
                                          is_user_initiated);
  return TRUE;
}

gboolean update_engine_service_reset_status(UpdateEngineService* self,
                                            GError **error) {
  *error = NULL;
  return self->update_attempter_->ResetStatus();
}


gboolean update_engine_service_get_status(UpdateEngineService* self,
                                          int64_t* last_checked_time,
                                          double* progress,
                                          gchar** current_operation,
                                          gchar** new_version,
                                          int64_t* new_size,
                                          GError **error) {
  string current_op;
  string new_version_str;

  CHECK(self->update_attempter_->GetStatus(last_checked_time,
                                           progress,
                                           &current_op,
                                           &new_version_str,
                                           new_size));

  *current_operation = g_strdup(current_op.c_str());
  *new_version = g_strdup(new_version_str.c_str());
  if (!(*current_operation && *new_version)) {
    *error = NULL;
    return FALSE;
  }
  return TRUE;
}

gboolean update_engine_service_get_track(UpdateEngineService* self,
                                         gchar** track,
                                         GError **error) {
  string track_str =
      chromeos_update_engine::OmahaRequestDeviceParams::GetDeviceTrack();
  *track = g_strdup(track_str.c_str());
  return TRUE;
}

gboolean update_engine_service_reboot_if_needed(UpdateEngineService* self,
                                                GError **error) {
  if (!self->update_attempter_->RebootIfNeeded()) {
    *error = NULL;
    return FALSE;
  }
  return TRUE;
}

gboolean update_engine_service_set_track(UpdateEngineService* self,
                                         gchar* track,
                                         GError **error) {
  if (track) {
    LOG(INFO) << "Setting track to: " << track;
    if (!chromeos_update_engine::OmahaRequestDeviceParams::SetDeviceTrack(
            track)) {
      *error = NULL;
      return FALSE;
    }
  }
  return TRUE;
}

gboolean update_engine_service_emit_status_update(
    UpdateEngineService* self,
    gint64 last_checked_time,
    gdouble progress,
    const gchar* current_operation,
    const gchar* new_version,
    gint64 new_size) {
  g_signal_emit(self,
                status_update_signal,
                0,
                last_checked_time,
                progress,
                current_operation,
                new_version,
                new_size);
  return TRUE;
}
