// Copyright 2018 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 "dlcservice/dlc_service.h"

#include <algorithm>
#include <memory>
#include <utility>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>
#include <brillo/errors/error.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/dlcservice/dbus-constants.h>

#include "dlcservice/dlc.h"
#include "dlcservice/error.h"
#include "dlcservice/ref_count.h"
#include "dlcservice/utils.h"

using base::Callback;
using brillo::ErrorPtr;
using brillo::MessageLoop;
using std::string;
using update_engine::Operation;
using update_engine::StatusResult;

namespace dlcservice {

DlcService::DlcService()
    : periodic_install_check_id_(MessageLoop::kTaskIdNull),
      weak_ptr_factory_(this) {}

DlcService::~DlcService() {
  if (periodic_install_check_id_ != MessageLoop::kTaskIdNull &&
      !brillo::MessageLoop::current()->CancelTask(periodic_install_check_id_))
    LOG(ERROR)
        << "Failed to cancel delayed update_engine check during cleanup.";
}

void DlcService::Initialize() {
  auto* system_state = SystemState::Get();
  const auto prefs_dir = system_state->dlc_prefs_dir();
  if (!base::PathExists(prefs_dir)) {
    CHECK(CreateDir(prefs_dir))
        << "Failed to create dlc prefs directory: " << prefs_dir;
  }

  dlc_manager_ = std::make_unique<DlcManager>();

  // Register D-Bus signal callbacks.
  system_state->update_engine()->RegisterStatusUpdateAdvancedSignalHandler(
      base::Bind(&DlcService::OnStatusUpdateAdvancedSignal,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&DlcService::OnStatusUpdateAdvancedSignalConnected,
                 weak_ptr_factory_.GetWeakPtr()));

  system_state->session_manager()->RegisterSessionStateChangedSignalHandler(
      base::Bind(&DlcService::OnSessionStateChangedSignal,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&DlcService::OnSessionStateChangedSignalConnected,
                 weak_ptr_factory_.GetWeakPtr()));

  dlc_manager_->Initialize();
}

bool DlcService::Install(const DlcId& id,
                         const string& omaha_url,
                         ErrorPtr* err) {
  bool result = InstallInternal(id, omaha_url, err);
  // Only send error metrics in here. Install success metrics is sent in
  // |DlcBase|.
  if (!result) {
    SystemState::Get()->metrics()->SendInstallResultFailure(err);
    Error::ConvertToDbusError(err);
  }
  return result;
}

bool DlcService::InstallInternal(const DlcId& id,
                                 const string& omaha_url,
                                 ErrorPtr* err) {
  // TODO(ahassani): Currently, we create the DLC images even if later we find
  // out the update_engine is busy and we have to delete the images. It would be
  // better to know the update_engine status beforehand so we can tell the DLC
  // to not create the images, just load them if it can. We can do this more
  // reliably by caching the last status we saw from update_engine, rather than
  // pulling for it on every install request. That would also allows us to
  // properly queue the incoming install requests.

  // Try to install and figure out if install through update_engine is needed.
  bool external_install_needed = false;
  if (!dlc_manager_->Install(id, &external_install_needed, err)) {
    LOG(ERROR) << "Failed to install DLC=" << id;
    return false;
  }

  // Install through update_engine only if needed.
  if (!external_install_needed)
    return true;

  if (!InstallWithUpdateEngine(id, omaha_url, err)) {
    // dlcservice must cancel the install as update_engine won't be able to
    // install the initialized DLC.
    CancelInstall(*err);
    return false;
  }

  // By now the update_engine is installing the DLC, so schedule a periodic
  // install checker in case we miss update_engine signals.
  SchedulePeriodicInstallCheck();

  return true;
}

bool DlcService::InstallWithUpdateEngine(const DlcId& id,
                                         const string& omaha_url,
                                         ErrorPtr* err) {
  // Check what state update_engine is in.
  if (SystemState::Get()->update_engine_status().current_operation() ==
      update_engine::UPDATED_NEED_REBOOT) {
    *err =
        Error::Create(FROM_HERE, kErrorNeedReboot,
                      "Update Engine applied update, device needs a reboot.");
    return false;
  }

  LOG(INFO) << "Sending request to update_engine to install DLC=" << id;
  // Invokes update_engine to install the DLC.
  ErrorPtr tmp_err;
  installing_dlc_id_ = id;
  if (!SystemState::Get()->update_engine()->AttemptInstall(omaha_url, {id},
                                                           &tmp_err)) {
    // TODO(kimjae): need update engine to propagate correct error message by
    // passing in |ErrorPtr| and being set within update engine, current default
    // is to indicate that update engine is updating because there is no way an
    // install should have taken place if not through dlcservice. (could also be
    // the case that an update applied between the time of the last status check
    // above, but just return |kErrorBusy| because the next time around if an
    // update has been applied and is in a reboot needed state, it will indicate
    // correctly then).
    LOG(ERROR) << "Update Engine failed to install requested DLCs: "
               << (tmp_err ? Error::ToString(tmp_err)
                           : "Missing error from update engine proxy.");
    *err =
        Error::Create(FROM_HERE, kErrorBusy,
                      "Update Engine failed to schedule install operations.");
    return false;
  }

  return true;
}

bool DlcService::Uninstall(const string& id, brillo::ErrorPtr* err) {
  bool result = dlc_manager_->Uninstall(id, err);
  SystemState::Get()->metrics()->SendUninstallResult(err);
  if (!result)
    Error::ConvertToDbusError(err);

  return result;
}

bool DlcService::Purge(const string& id, brillo::ErrorPtr* err) {
  return dlc_manager_->Purge(id, err);
}

const DlcBase* DlcService::GetDlc(const DlcId& id, brillo::ErrorPtr* err) {
  return dlc_manager_->GetDlc(id, err);
}

DlcIdList DlcService::GetInstalled() {
  return dlc_manager_->GetInstalled();
}

DlcIdList DlcService::GetExistingDlcs() {
  return dlc_manager_->GetExistingDlcs();
}

DlcIdList DlcService::GetDlcsToUpdate() {
  return dlc_manager_->GetDlcsToUpdate();
}

bool DlcService::InstallCompleted(const DlcIdList& ids, ErrorPtr* err) {
  return dlc_manager_->InstallCompleted(ids, err);
}

bool DlcService::UpdateCompleted(const DlcIdList& ids, ErrorPtr* err) {
  return dlc_manager_->UpdateCompleted(ids, err);
}

bool DlcService::FinishInstall(ErrorPtr* err) {
  if (!installing_dlc_id_) {
    LOG(ERROR) << "No DLC installation to finish.";
    return false;
  }
  auto id = installing_dlc_id_.value();
  installing_dlc_id_.reset();
  return dlc_manager_->FinishInstall(id, err);
}

void DlcService::CancelInstall(const ErrorPtr& err_in) {
  if (!installing_dlc_id_) {
    LOG(ERROR) << "No DLC installation to cancel.";
    return;
  }
  auto id = installing_dlc_id_.value();
  installing_dlc_id_.reset();
  ErrorPtr tmp_err;
  if (!dlc_manager_->CancelInstall(id, err_in, &tmp_err))
    LOG(ERROR) << "Failed to cancel install for DLC=" << id;
}

void DlcService::PeriodicInstallCheck() {
  periodic_install_check_id_ = MessageLoop::kTaskIdNull;

  // If we're not installing anything anymore, no need to schedule again.
  if (!installing_dlc_id_)
    return;

  const int kNotSeenStatusDelay = 10;
  auto* system_state = SystemState::Get();
  if ((system_state->clock()->Now() -
       system_state->update_engine_status_timestamp()) >
      base::TimeDelta::FromSeconds(kNotSeenStatusDelay)) {
    if (GetUpdateEngineStatus()) {
      ErrorPtr tmp_error;
      if (!HandleStatusResult(&tmp_error)) {
        return;
      }
    }
  }

  SchedulePeriodicInstallCheck();
}

void DlcService::SchedulePeriodicInstallCheck() {
  if (periodic_install_check_id_ != MessageLoop::kTaskIdNull) {
    LOG(INFO) << "Another periodic install check already scheduled.";
    return;
  }

  periodic_install_check_id_ = brillo::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&DlcService::PeriodicInstallCheck,
                 weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromSeconds(kUECheckTimeout));
}

bool DlcService::HandleStatusResult(brillo::ErrorPtr* err) {
  // If we are not installing any DLC(s), no need to even handle status result.
  if (!installing_dlc_id_)
    return true;

  const StatusResult& status = SystemState::Get()->update_engine_status();
  if (!status.is_install()) {
    *err = Error::CreateInternal(
        FROM_HERE, error::kFailedInstallInUpdateEngine,
        "Signal from update_engine indicates that it's not for an install, but "
        "dlcservice was waiting for an install.");
    CancelInstall(*err);
    SystemState::Get()->metrics()->SendInstallResultFailure(err);
    return false;
  }

  switch (status.current_operation()) {
    case update_engine::UPDATED_NEED_REBOOT:
      *err =
          Error::Create(FROM_HERE, kErrorNeedReboot,
                        "Update Engine applied update, device needs a reboot.");
      break;
    case Operation::IDLE:
      LOG(INFO)
          << "Signal from update_engine, proceeding to complete installation.";
      // Send metrics in |DlcBase::FinishInstall| and not here since we might
      // be executing this call for multiple DLCs.
      if (!FinishInstall(err)) {
        LOG(ERROR) << "Failed to finish install.";
        return false;
      }
      return true;
    case Operation::REPORTING_ERROR_EVENT:
      *err =
          Error::CreateInternal(FROM_HERE, error::kFailedInstallInUpdateEngine,
                                "update_engine indicates reporting failure.");
      break;
    // Only when update_engine's |Operation::DOWNLOADING| should the DLC send
    // |DlcState::INSTALLING|. Majority of the install process for DLC(s) is
    // during |Operation::DOWNLOADING|, this also means that only a single
    // growth from 0.0 to 1.0 for progress reporting will happen.
    case Operation::DOWNLOADING:
      // TODO(ahassani): Add unittest for this.
      dlc_manager_->ChangeProgress(status.progress());

      FALLTHROUGH;
    default:
      return true;
  }

  CancelInstall(*err);
  SystemState::Get()->metrics()->SendInstallResultFailure(err);
  return false;
}

bool DlcService::GetUpdateEngineStatus() {
  StatusResult status_result;
  if (!SystemState::Get()->update_engine()->GetStatusAdvanced(&status_result,
                                                              nullptr)) {
    LOG(ERROR) << "Failed to get update_engine status, will try again later.";
    return false;
  }
  SystemState::Get()->set_update_engine_status(status_result);
  LOG(INFO) << "Got update_engine status: "
            << status_result.current_operation();
  return true;
}

void DlcService::OnStatusUpdateAdvancedSignal(
    const StatusResult& status_result) {
  // Always set the status.
  SystemState::Get()->set_update_engine_status(status_result);

  ErrorPtr err;
  if (!HandleStatusResult(&err))
    DCHECK(err.get());
}

void DlcService::OnStatusUpdateAdvancedSignalConnected(
    const string& interface_name, const string& signal_name, bool success) {
  if (!success) {
    LOG(ERROR) << "Failed to connect to update_engine's StatusUpdate signal.";
  }
  if (!GetUpdateEngineStatus()) {
    // As a last resort, if we couldn't get the status, just set the status to
    // IDLE, so things can move forward. This is mostly the case because when
    // update_engine comes up its first status is IDLE and it will stay that way
    // for quite a while.
    StatusResult status;
    status.set_current_operation(Operation::IDLE);
    status.set_is_install(false);
  }
}

void DlcService::OnSessionStateChangedSignalConnected(
    const string& interface_name, const string& signal_name, bool success) {
  if (!success) {
    LOG(ERROR) << "Failed to connect to session_manager's SessionStateChanged "
               << "signal.";
  }
}

void DlcService::OnSessionStateChangedSignal(const std::string& state) {
  UserRefCount::SessionChanged(state);
}

}  // namespace dlcservice
