//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/update_manager/real_updater_provider.h"

#include <inttypes.h>

#include <string>

#include <base/bind.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <update_engine/dbus-constants.h>

#include "update_engine/common/clock_interface.h"
#include "update_engine/common/prefs.h"
#include "update_engine/omaha_request_params.h"
#include "update_engine/update_attempter.h"

using base::StringPrintf;
using base::Time;
using base::TimeDelta;
using chromeos_update_engine::OmahaRequestParams;
using chromeos_update_engine::SystemState;
using std::string;

namespace chromeos_update_manager {

// A templated base class for all update related variables. Provides uniform
// construction and a system state handle.
template<typename T>
class UpdaterVariableBase : public Variable<T> {
 public:
  UpdaterVariableBase(const string& name, VariableMode mode,
                      SystemState* system_state)
      : Variable<T>(name, mode), system_state_(system_state) {}

 protected:
  // The system state used for pulling information from the updater.
  inline SystemState* system_state() const { return system_state_; }

 private:
  SystemState* const system_state_;
};

// Helper class for issuing a GetStatus() to the UpdateAttempter.
class GetStatusHelper {
 public:
  GetStatusHelper(SystemState* system_state, string* errmsg) {
    is_success_ = system_state->update_attempter()->GetStatus(
        &last_checked_time_, &progress_, &update_status_, &new_version_,
        &payload_size_);
    if (!is_success_ && errmsg)
      *errmsg = "Failed to get a status update from the update engine";
  }

  inline bool is_success() { return is_success_; }
  inline int64_t last_checked_time() { return last_checked_time_; }
  inline double progress() { return progress_; }
  inline const string& update_status() { return update_status_; }
  inline const string& new_version() { return new_version_; }
  inline int64_t payload_size() { return payload_size_; }

 private:
  bool is_success_;
  int64_t last_checked_time_;
  double progress_;
  string update_status_;
  string new_version_;
  int64_t payload_size_;
};

// A variable reporting the time when a last update check was issued.
class LastCheckedTimeVariable : public UpdaterVariableBase<Time> {
 public:
  LastCheckedTimeVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}

 private:
  const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    GetStatusHelper raw(system_state(), errmsg);
    if (!raw.is_success())
      return nullptr;

    return new Time(Time::FromTimeT(raw.last_checked_time()));
  }

  DISALLOW_COPY_AND_ASSIGN(LastCheckedTimeVariable);
};

// A variable reporting the update (download) progress as a decimal fraction
// between 0.0 and 1.0.
class ProgressVariable : public UpdaterVariableBase<double> {
 public:
  ProgressVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<double>(name, kVariableModePoll, system_state) {}

 private:
  const double* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    GetStatusHelper raw(system_state(), errmsg);
    if (!raw.is_success())
      return nullptr;

    if (raw.progress() < 0.0 || raw.progress() > 1.0) {
      if (errmsg) {
        *errmsg = StringPrintf("Invalid progress value received: %f",
                               raw.progress());
      }
      return nullptr;
    }

    return new double(raw.progress());
  }

  DISALLOW_COPY_AND_ASSIGN(ProgressVariable);
};

// A variable reporting the stage in which the update process is.
class StageVariable : public UpdaterVariableBase<Stage> {
 public:
  StageVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<Stage>(name, kVariableModePoll, system_state) {}

 private:
  struct CurrOpStrToStage {
    const char* str;
    Stage stage;
  };
  static const CurrOpStrToStage curr_op_str_to_stage[];

  // Note: the method is defined outside the class so arraysize can work.
  const Stage* GetValue(TimeDelta /* timeout */, string* errmsg) override;

  DISALLOW_COPY_AND_ASSIGN(StageVariable);
};

const StageVariable::CurrOpStrToStage StageVariable::curr_op_str_to_stage[] = {
  {update_engine::kUpdateStatusIdle, Stage::kIdle},
  {update_engine::kUpdateStatusCheckingForUpdate, Stage::kCheckingForUpdate},
  {update_engine::kUpdateStatusUpdateAvailable, Stage::kUpdateAvailable},
  {update_engine::kUpdateStatusDownloading, Stage::kDownloading},
  {update_engine::kUpdateStatusVerifying, Stage::kVerifying},
  {update_engine::kUpdateStatusFinalizing, Stage::kFinalizing},
  {update_engine::kUpdateStatusUpdatedNeedReboot, Stage::kUpdatedNeedReboot},
  {  // NOLINT(whitespace/braces)
    update_engine::kUpdateStatusReportingErrorEvent,
    Stage::kReportingErrorEvent
  },
  {update_engine::kUpdateStatusAttemptingRollback, Stage::kAttemptingRollback},
};

const Stage* StageVariable::GetValue(TimeDelta /* timeout */,
                                     string* errmsg) {
  GetStatusHelper raw(system_state(), errmsg);
  if (!raw.is_success())
    return nullptr;

  for (auto& key_val : curr_op_str_to_stage)
    if (raw.update_status() == key_val.str)
      return new Stage(key_val.stage);

  if (errmsg)
    *errmsg = string("Unknown update status: ") + raw.update_status();
  return nullptr;
}

// A variable reporting the version number that an update is updating to.
class NewVersionVariable : public UpdaterVariableBase<string> {
 public:
  NewVersionVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}

 private:
  const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    GetStatusHelper raw(system_state(), errmsg);
    if (!raw.is_success())
      return nullptr;

    return new string(raw.new_version());
  }

  DISALLOW_COPY_AND_ASSIGN(NewVersionVariable);
};

// A variable reporting the size of the update being processed in bytes.
class PayloadSizeVariable : public UpdaterVariableBase<int64_t> {
 public:
  PayloadSizeVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<int64_t>(name, kVariableModePoll, system_state) {}

 private:
  const int64_t* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    GetStatusHelper raw(system_state(), errmsg);
    if (!raw.is_success())
      return nullptr;

    if (raw.payload_size() < 0) {
      if (errmsg)
        *errmsg = string("Invalid payload size: %" PRId64, raw.payload_size());
      return nullptr;
    }

    return new int64_t(raw.payload_size());
  }

  DISALLOW_COPY_AND_ASSIGN(PayloadSizeVariable);
};

// A variable reporting the point in time an update last completed in the
// current boot cycle.
//
// TODO(garnold) In general, both the current boottime and wallclock time
// readings should come from the time provider and be moderated by the
// evaluation context, so that they are uniform throughout the evaluation of a
// policy request.
class UpdateCompletedTimeVariable : public UpdaterVariableBase<Time> {
 public:
  UpdateCompletedTimeVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}

 private:
  const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    Time update_boottime;
    if (!system_state()->update_attempter()->GetBootTimeAtUpdate(
            &update_boottime)) {
      if (errmsg)
        *errmsg = "Update completed time could not be read";
      return nullptr;
    }

    chromeos_update_engine::ClockInterface* clock = system_state()->clock();
    Time curr_boottime = clock->GetBootTime();
    if (curr_boottime < update_boottime) {
      if (errmsg)
        *errmsg = "Update completed time more recent than current time";
      return nullptr;
    }
    TimeDelta duration_since_update = curr_boottime - update_boottime;
    return new Time(clock->GetWallclockTime() - duration_since_update);
  }

  DISALLOW_COPY_AND_ASSIGN(UpdateCompletedTimeVariable);
};

// Variables reporting the current image channel.
class CurrChannelVariable : public UpdaterVariableBase<string> {
 public:
  CurrChannelVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}

 private:
  const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    OmahaRequestParams* request_params = system_state()->request_params();
    string channel = request_params->current_channel();
    if (channel.empty()) {
      if (errmsg)
        *errmsg = "No current channel";
      return nullptr;
    }
    return new string(channel);
  }

  DISALLOW_COPY_AND_ASSIGN(CurrChannelVariable);
};

// Variables reporting the new image channel.
class NewChannelVariable : public UpdaterVariableBase<string> {
 public:
  NewChannelVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}

 private:
  const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
    OmahaRequestParams* request_params = system_state()->request_params();
    string channel = request_params->target_channel();
    if (channel.empty()) {
      if (errmsg)
        *errmsg = "No new channel";
      return nullptr;
    }
    return new string(channel);
  }

  DISALLOW_COPY_AND_ASSIGN(NewChannelVariable);
};

// A variable class for reading Boolean prefs values.
class BooleanPrefVariable
    : public AsyncCopyVariable<bool>,
      public chromeos_update_engine::PrefsInterface::ObserverInterface {
 public:
  BooleanPrefVariable(const string& name,
                      chromeos_update_engine::PrefsInterface* prefs,
                      const char* key,
                      bool default_val)
      : AsyncCopyVariable<bool>(name),
        prefs_(prefs),
        key_(key),
        default_val_(default_val) {
    prefs->AddObserver(key, this);
    OnPrefSet(key);
  }
  ~BooleanPrefVariable() {
    prefs_->RemoveObserver(key_, this);
  }

 private:
  // Reads the actual value from the Prefs instance and updates the Variable
  // value.
  void OnPrefSet(const string& key) override {
    bool result = default_val_;
    if (prefs_ && prefs_->Exists(key_) && !prefs_->GetBoolean(key_, &result))
      result = default_val_;
    // AsyncCopyVariable will take care of values that didn't change.
    SetValue(result);
  }

  void OnPrefDeleted(const string& key) override {
    SetValue(default_val_);
  }

  chromeos_update_engine::PrefsInterface* prefs_;

  // The Boolean preference key and default value.
  const char* const key_;
  const bool default_val_;

  DISALLOW_COPY_AND_ASSIGN(BooleanPrefVariable);
};

// A variable returning the number of consecutive failed update checks.
class ConsecutiveFailedUpdateChecksVariable
    : public UpdaterVariableBase<unsigned int> {
 public:
  ConsecutiveFailedUpdateChecksVariable(const string& name,
                                        SystemState* system_state)
      : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
                                          system_state) {}

 private:
  const unsigned int* GetValue(TimeDelta /* timeout */,
                               string* /* errmsg */) override {
    return new unsigned int(
        system_state()->update_attempter()->consecutive_failed_update_checks());
  }

  DISALLOW_COPY_AND_ASSIGN(ConsecutiveFailedUpdateChecksVariable);
};

// A variable returning the server-dictated poll interval.
class ServerDictatedPollIntervalVariable
    : public UpdaterVariableBase<unsigned int> {
 public:
  ServerDictatedPollIntervalVariable(const string& name,
                                     SystemState* system_state)
      : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
                                          system_state) {}

 private:
  const unsigned int* GetValue(TimeDelta /* timeout */,
                               string* /* errmsg */) override {
    return new unsigned int(
        system_state()->update_attempter()->server_dictated_poll_interval());
  }

  DISALLOW_COPY_AND_ASSIGN(ServerDictatedPollIntervalVariable);
};

// An async variable that tracks changes to forced update requests.
class ForcedUpdateRequestedVariable
    : public UpdaterVariableBase<UpdateRequestStatus> {
 public:
  ForcedUpdateRequestedVariable(const string& name, SystemState* system_state)
      : UpdaterVariableBase<UpdateRequestStatus>::UpdaterVariableBase(
          name, kVariableModeAsync, system_state) {
    system_state->update_attempter()->set_forced_update_pending_callback(
        new base::Callback<void(bool, bool)>(  // NOLINT(readability/function)
            base::Bind(&ForcedUpdateRequestedVariable::Reset,
                       base::Unretained(this))));
  }

 private:
  const UpdateRequestStatus* GetValue(TimeDelta /* timeout */,
                                      string* /* errmsg */) override {
    return new UpdateRequestStatus(update_request_status_);
  }

  void Reset(bool forced_update_requested, bool is_interactive) {
    UpdateRequestStatus new_value = UpdateRequestStatus::kNone;
    if (forced_update_requested)
      new_value = (is_interactive ? UpdateRequestStatus::kInteractive :
                   UpdateRequestStatus::kPeriodic);
    if (update_request_status_ != new_value) {
      update_request_status_ = new_value;
      NotifyValueChanged();
    }
  }

  UpdateRequestStatus update_request_status_ = UpdateRequestStatus::kNone;

  DISALLOW_COPY_AND_ASSIGN(ForcedUpdateRequestedVariable);
};

// RealUpdaterProvider methods.

RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
  : system_state_(system_state),
    var_updater_started_time_("updater_started_time",
                              system_state->clock()->GetWallclockTime()),
    var_last_checked_time_(
        new LastCheckedTimeVariable("last_checked_time", system_state_)),
    var_update_completed_time_(
        new UpdateCompletedTimeVariable("update_completed_time",
                                        system_state_)),
    var_progress_(new ProgressVariable("progress", system_state_)),
    var_stage_(new StageVariable("stage", system_state_)),
    var_new_version_(new NewVersionVariable("new_version", system_state_)),
    var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
    var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
    var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
    var_p2p_enabled_(
        new BooleanPrefVariable("p2p_enabled", system_state_->prefs(),
                                chromeos_update_engine::kPrefsP2PEnabled,
                                false)),
    var_cellular_enabled_(
        new BooleanPrefVariable(
            "cellular_enabled", system_state_->prefs(),
            chromeos_update_engine::kPrefsUpdateOverCellularPermission,
            false)),
    var_consecutive_failed_update_checks_(
        new ConsecutiveFailedUpdateChecksVariable(
            "consecutive_failed_update_checks", system_state_)),
    var_server_dictated_poll_interval_(
        new ServerDictatedPollIntervalVariable(
            "server_dictated_poll_interval", system_state_)),
    var_forced_update_requested_(
        new ForcedUpdateRequestedVariable(
            "forced_update_requested", system_state_)) {}

}  // namespace chromeos_update_manager
