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

#include <base/bind.h>
#include <base/callback.h>
#include <base/logging.h>
#include <base/time/time.h>

#include "update_engine/common/utils.h"
#if USE_LIBCROS
#include "update_engine/libcros_proxy.h"
#endif
#include "update_engine/update_manager/generic_variables.h"
#include "update_engine/update_manager/variable.h"

using std::string;

namespace chromeos_update_manager {

namespace {

// The maximum number of consecutive failures before returning the default
// constructor value for T instead of failure.
const int kRetryPollVariableMaxRetry = 5;

// The polling interval to be used whenever GetValue() returns an error.
const int kRetryPollVariableRetryIntervalSeconds = 5 * 60;

// The RetryPollVariable variable is a polling variable that allows the function
// returning the value to fail a few times and shortens the polling rate when
// that happens.
template <typename T>
class RetryPollVariable : public Variable<T> {
 public:
  RetryPollVariable(const string& name,
                    const base::TimeDelta poll_interval,
                    base::Callback<bool(T* res)> func)
      : Variable<T>(name, poll_interval),
        func_(func),
        base_interval_(poll_interval) {
    DCHECK_LT(kRetryPollVariableRetryIntervalSeconds,
              base_interval_.InSeconds());
  }

 protected:
  // Variable override.
  const T* GetValue(base::TimeDelta /* timeout */,
                    string* /* errmsg */) override {
    std::unique_ptr<T> result(new T());
    if (!func_.Run(result.get())) {
      if (failed_attempts_ >= kRetryPollVariableMaxRetry) {
        // Give up on the retries, set back the desired polling interval and
        // return the default.
        this->SetPollInterval(base_interval_);
        return result.release();
      }
      this->SetPollInterval(
          base::TimeDelta::FromSeconds(kRetryPollVariableRetryIntervalSeconds));
      failed_attempts_++;
      return nullptr;
    }
    failed_attempts_ = 0;
    this->SetPollInterval(base_interval_);
    return result.release();
  }

 private:
  // The function to be called, stored as a base::Callback.
  base::Callback<bool(T*)> func_;

  // The desired polling interval when |func_| works and returns true.
  base::TimeDelta base_interval_;

  // The number of consecutive failed attempts made.
  int failed_attempts_ = 0;

  DISALLOW_COPY_AND_ASSIGN(RetryPollVariable);
};

}  // namespace

bool RealSystemProvider::Init() {
  var_is_normal_boot_mode_.reset(
      new ConstCopyVariable<bool>("is_normal_boot_mode",
                                  hardware_->IsNormalBootMode()));

  var_is_official_build_.reset(
      new ConstCopyVariable<bool>("is_official_build",
                                  hardware_->IsOfficialBuild()));

  var_is_oobe_complete_.reset(
      new CallCopyVariable<bool>(
          "is_oobe_complete",
          base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete,
                     base::Unretained(hardware_), nullptr)));

  var_num_slots_.reset(
      new ConstCopyVariable<unsigned int>(
          "num_slots", boot_control_->GetNumSlots()));

  var_kiosk_required_platform_version_.reset(new RetryPollVariable<string>(
      "kiosk_required_platform_version",
      base::TimeDelta::FromHours(5),  // Same as Chrome's CWS poll.
      base::Bind(&RealSystemProvider::GetKioskAppRequiredPlatformVersion,
                 base::Unretained(this))));

  return true;
}

bool RealSystemProvider::GetKioskAppRequiredPlatformVersion(
    string* required_platform_version) {
#if USE_LIBCROS
  brillo::ErrorPtr error;
  if (!libcros_proxy_->service_interface_proxy()
           ->GetKioskAppRequiredPlatformVersion(required_platform_version,
                                                &error)) {
    LOG(WARNING) << "Failed to get kiosk required platform version";
    required_platform_version->clear();
    return false;
  }
#endif

  return true;
}

}  // namespace chromeos_update_manager
