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

#ifndef UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_
#define UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_

#include <memory>
#include <string>

#include <base/bind.h>
#include <base/location.h>
#include <brillo/message_loops/message_loop.h>

#include "update_engine/update_manager/evaluation_context.h"

namespace chromeos_update_manager {

template <typename R, typename... Args>
EvalStatus UpdateManager::EvaluatePolicy(
    EvaluationContext* ec,
    EvalStatus (Policy::*policy_method)(
        EvaluationContext*, State*, std::string*, R*, Args...) const,
    R* result,
    Args... args) {
  // If expiration timeout fired, dump the context and reset expiration.
  // IMPORTANT: We must still proceed with evaluation of the policy in this
  // case, so that the evaluation time (and corresponding reevaluation timeouts)
  // are readjusted.
  if (ec->is_expired()) {
    LOG(WARNING) << "Request timed out, evaluation context: "
                 << ec->DumpContext();
    ec->ResetExpiration();
  }

  // Reset the evaluation context.
  ec->ResetEvaluation();

  const std::string policy_name = policy_->PolicyRequestName(policy_method);

  // First try calling the actual policy.
  std::string error;
  EvalStatus status = (policy_.get()->*policy_method)(
      ec, state_.get(), &error, result, args...);
  // If evaluating the main policy failed, defer to the default policy.
  if (status == EvalStatus::kFailed) {
    LOG(WARNING) << "Evaluating policy failed: " << error
                 << "\nEvaluation context: " << ec->DumpContext();
    error.clear();
    status = (default_policy_.*policy_method)(
        ec, state_.get(), &error, result, args...);
    if (status == EvalStatus::kFailed) {
      LOG(WARNING) << "Evaluating default policy failed: " << error;
    } else if (status == EvalStatus::kAskMeAgainLater) {
      LOG(ERROR)
          << "Default policy would block; this is a bug, forcing failure.";
      status = EvalStatus::kFailed;
    }
  }

  return status;
}

template <typename R, typename... Args>
void UpdateManager::OnPolicyReadyToEvaluate(
    std::shared_ptr<EvaluationContext> ec,
    base::Callback<void(EvalStatus status, const R& result)> callback,
    EvalStatus (Policy::*policy_method)(
        EvaluationContext*, State*, std::string*, R*, Args...) const,
    Args... args) {
  // Evaluate the policy.
  R result;
  EvalStatus status = EvaluatePolicy(ec.get(), policy_method, &result, args...);

  if (status != EvalStatus::kAskMeAgainLater) {
    // AsyncPolicyRequest finished.
    callback.Run(status, result);
    return;
  }

  // Re-schedule the policy request based on used variables.
  base::Closure reeval_callback =
      base::Bind(&UpdateManager::OnPolicyReadyToEvaluate<R, Args...>,
                 base::Unretained(this),
                 ec,
                 callback,
                 policy_method,
                 args...);
  if (ec->RunOnValueChangeOrTimeout(reeval_callback))
    return;  // Reevaluation scheduled successfully.

  // Scheduling a reevaluation can fail because policy method didn't use any
  // non-const variable nor there's any time-based event that will change the
  // status of evaluation.  Alternatively, this may indicate an error in the use
  // of the scheduling interface.
  LOG(ERROR) << "Failed to schedule a reevaluation of policy "
             << policy_->PolicyRequestName(policy_method) << "; this is a bug.";
  callback.Run(status, result);
}

template <typename R, typename... ActualArgs, typename... ExpectedArgs>
EvalStatus UpdateManager::PolicyRequest(
    EvalStatus (Policy::*policy_method)(
        EvaluationContext*, State*, std::string*, R*, ExpectedArgs...) const,
    R* result,
    ActualArgs... args) {
  auto ec = std::make_shared<EvaluationContext>(evaluation_timeout_);
  // A PolicyRequest always consists on a single evaluation on a new
  // EvaluationContext.
  // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
  // explicitly instantiate EvaluatePolicy with the latter in lieu of the
  // former.
  EvalStatus ret = EvaluatePolicy<R, ExpectedArgs...>(
      ec.get(), policy_method, result, args...);
  // Sync policy requests must not block, if they do then this is an error.
  DCHECK(EvalStatus::kAskMeAgainLater != ret);
  LOG_IF(WARNING, EvalStatus::kAskMeAgainLater == ret)
      << "Sync request used with an async policy; this is a bug";
  return ret;
}

template <typename R, typename... ActualArgs, typename... ExpectedArgs>
void UpdateManager::AsyncPolicyRequest(
    base::Callback<void(EvalStatus, const R& result)> callback,
    EvalStatus (Policy::*policy_method)(
        EvaluationContext*, State*, std::string*, R*, ExpectedArgs...) const,
    ActualArgs... args) {
  auto ec = std::make_shared<EvaluationContext>(
      evaluation_timeout_,
      expiration_timeout_,
      std::unique_ptr<base::Callback<void(EvaluationContext*)>>(
          new base::Callback<void(EvaluationContext*)>(
              base::Bind(&UpdateManager::UnregisterEvalContext,
                         weak_ptr_factory_.GetWeakPtr()))));
  if (!ec_repo_.insert(ec).second) {
    LOG(ERROR) << "Failed to register evaluation context; this is a bug.";
  }

  // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
  // explicitly instantiate UpdateManager::OnPolicyReadyToEvaluate with the
  // latter in lieu of the former.
  base::Closure eval_callback =
      base::Bind(&UpdateManager::OnPolicyReadyToEvaluate<R, ExpectedArgs...>,
                 base::Unretained(this),
                 ec,
                 callback,
                 policy_method,
                 args...);
  brillo::MessageLoop::current()->PostTask(FROM_HERE, eval_callback);
}

}  // namespace chromeos_update_manager

#endif  // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_
