// 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/dbus_manager.h"
#include "shill/event_dispatcher.h"
#include "shill/logging.h"
#include "shill/power_manager_proxy_interface.h"
#include "shill/proxy_factory.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,
                           ProxyFactory *proxy_factory)
    : dispatcher_(dispatcher),
      power_manager_proxy_(proxy_factory->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_);
}

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
