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

#include <map>
#include <string>

#include <base/bind.h>
#include <base/stl_util.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/control_interface.h"
#include "shill/dbus_manager.h"
#include "shill/event_dispatcher.h"
#include "shill/logging.h"
#include "shill/power_manager_proxy_interface.h"

using base::Bind;
using base::TimeDelta;
using base::Unretained;
using std::map;
using std::string;

namespace shill {

// static
const int PowerManager::kInvalidSuspendId = -1;
const char PowerManager::kSuspendDelayDescription[] = "shill";
const char PowerManager::kDarkSuspendDelayDescription[] = "shill";
const int PowerManager::kSuspendTimeoutMilliseconds = 15 * 1000;

PowerManager::PowerManager(EventDispatcher* dispatcher,
                           ControlInterface* control_interface)
    : dispatcher_(dispatcher),
      power_manager_proxy_(control_interface->CreatePowerManagerProxy(this)),
      suspend_delay_registered_(false),
      suspend_delay_id_(0),
      dark_suspend_delay_registered_(false),
      dark_suspend_delay_id_(0),
      suspending_(false),
      in_dark_resume_(false),
      current_suspend_id_(0),
      current_dark_suspend_id_(0) {}

PowerManager::~PowerManager() {}

void PowerManager::Start(
    DBusManager* dbus_manager,
    TimeDelta suspend_delay,
    const SuspendImminentCallback& suspend_imminent_callback,
    const SuspendDoneCallback& suspend_done_callback,
    const DarkSuspendImminentCallback& dark_suspend_imminent_callback) {
  power_manager_name_watcher_.reset(
      dbus_manager->CreateNameWatcher(
          power_manager::kPowerManagerServiceName,
          Bind(&PowerManager::OnPowerManagerAppeared, Unretained(this)),
          Bind(&PowerManager::OnPowerManagerVanished, Unretained(this))));

  suspend_delay_ = suspend_delay;
  suspend_imminent_callback_ = suspend_imminent_callback;
  suspend_done_callback_ = suspend_done_callback;
  dark_suspend_imminent_callback_ = dark_suspend_imminent_callback;
}

void PowerManager::Stop() {
  LOG(INFO) << __func__;
  power_manager_name_watcher_.reset();
  // We may attempt to unregister with a stale |suspend_delay_id_| if powerd
  // reappeared behind our back. It is safe to do so.
  if (suspend_delay_registered_)
    power_manager_proxy_->UnregisterSuspendDelay(suspend_delay_id_);
  if (dark_suspend_delay_registered_)
    power_manager_proxy_->UnregisterDarkSuspendDelay(dark_suspend_delay_id_);

  suspend_delay_registered_ = false;
  dark_suspend_delay_registered_ = false;
}

bool PowerManager::ReportSuspendReadiness() {
  if (!suspending_) {
    LOG(INFO) << __func__ << ": Suspend attempt ("
              << current_suspend_id_ << ") not active. Ignoring signal.";
    return false;
  }
  return power_manager_proxy_->ReportSuspendReadiness(suspend_delay_id_,
                                                      current_suspend_id_);
}

bool PowerManager::ReportDarkSuspendReadiness() {
  return power_manager_proxy_->ReportDarkSuspendReadiness(
      dark_suspend_delay_id_,
      current_dark_suspend_id_);
}

bool PowerManager::RecordDarkResumeWakeReason(const string& wake_reason) {
  return power_manager_proxy_->RecordDarkResumeWakeReason(wake_reason);
}

void PowerManager::OnSuspendImminent(int suspend_id) {
  LOG(INFO) << __func__ << "(" << suspend_id << ")";
  current_suspend_id_ = suspend_id;

  // If we're already suspending, don't call the |suspend_imminent_callback_|
  // again.
  if (!suspending_) {
    // Change the power state to suspending as soon as this signal is received
    // so that the manager can suppress auto-connect, for example.
    // Also, we must set this before running the callback below, because the
    // callback may synchronously report suspend readiness.
    suspending_ = true;
    suspend_imminent_callback_.Run();
  }
}

void PowerManager::OnSuspendDone(int suspend_id) {
  // NB: |suspend_id| could be -1. See OnPowerManagerVanished.
  LOG(INFO) << __func__ << "(" << suspend_id << ")";
  if (!suspending_) {
    LOG(WARNING) << "Recieved unexpected SuspendDone ("
                 << suspend_id << "). Ignoring.";
    return;
  }

  suspending_ = false;
  in_dark_resume_ = false;
  suspend_done_callback_.Run();
}

void PowerManager::OnDarkSuspendImminent(int suspend_id) {
  LOG(INFO) << __func__ << "(" << suspend_id << ")";
  if (!dark_suspend_delay_registered_) {
    LOG(WARNING) << "Ignoring DarkSuspendImminent signal from powerd. shill "
                 << "does not have a dark suspend delay registered. This "
                 << "means that shill is not guaranteed any time before a "
                 << "resuspend.";
    return;
  }
  in_dark_resume_ = true;
  current_dark_suspend_id_ = suspend_id;
  dark_suspend_imminent_callback_.Run();
}

void PowerManager::OnPowerManagerAppeared(const string& /*name*/,
                                          const string& /*owner*/) {
  LOG(INFO) << __func__;
  CHECK(!suspend_delay_registered_);
  if (power_manager_proxy_->RegisterSuspendDelay(suspend_delay_,
                                                 kSuspendDelayDescription,
                                                 &suspend_delay_id_))
    suspend_delay_registered_ = true;

  if (power_manager_proxy_->RegisterDarkSuspendDelay(
      suspend_delay_,
      kDarkSuspendDelayDescription,
      &dark_suspend_delay_id_))
    dark_suspend_delay_registered_ = true;
}

void PowerManager::OnPowerManagerVanished(const string& /*name*/) {
  LOG(INFO) << __func__;
  // If powerd vanished during a suspend, we need to wake ourselves up.
  if (suspending_)
    OnSuspendDone(kInvalidSuspendId);
  suspend_delay_registered_ = false;
  dark_suspend_delay_registered_ = false;
}

}  // namespace shill
