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

#include <chromeos/dbus/service_constants.h>
#include <google/protobuf/message_lite.h>

#include "power_manager/proto_bindings/suspend.pb.h"
#include "wimax_manager/dbus_control.h"
#include "wimax_manager/manager.h"
#include "wimax_manager/power_manager_dbus_proxy.h"

using std::string;
using std::vector;

namespace wimax_manager {

namespace {

const uint32_t kDefaultSuspendDelayInMilliSeconds = 5000;  // 5s
const uint32_t kSuspendTimeoutInSeconds = 15;  // 15s
const char kSuspendDelayDescription[] = "wimax-manager";

// Serializes |protobuf| to |out| and returns true on success.
bool SerializeProtocolBuffer(const google::protobuf::MessageLite &protobuf,
                             vector<uint8_t> *out) {
  CHECK(out);

  out->clear();
  string serialized_protobuf;
  if (!protobuf.SerializeToString(&serialized_protobuf))
    return false;

  out->assign(serialized_protobuf.begin(), serialized_protobuf.end());
  return true;
}

// Deserializes |serialized_protobuf| to |protobuf_out| and returns true on
// success.
bool DeserializeProtocolBuffer(const vector<uint8_t> &serialized_protobuf,
                               google::protobuf::MessageLite *protobuf_out) {
  CHECK(protobuf_out);

  if (serialized_protobuf.empty())
    return false;

  return protobuf_out->ParseFromArray(&serialized_protobuf.front(),
                                      serialized_protobuf.size());
}

}  // namespace

PowerManager::PowerManager(Manager *wimax_manager)
    : suspend_delay_registered_(false),
      suspend_delay_id_(0),
      suspended_(false),
      wimax_manager_(wimax_manager) {
  CHECK(wimax_manager_);
}

PowerManager::~PowerManager() {
  Finalize();
}

void PowerManager::Initialize() {
  // TODO(benchan): May need to check if power manager is running and defer
  // the invocation of RegisterSuspendDelay when necessary.
  RegisterSuspendDelay(
      base::TimeDelta::FromMilliseconds(kDefaultSuspendDelayInMilliSeconds),
      kSuspendDelayDescription);
}

void PowerManager::Finalize() {
  suspend_timeout_timer_.Stop();
  UnregisterSuspendDelay();
}

void PowerManager::RegisterSuspendDelay(base::TimeDelta timeout,
                                        const string &description) {
  if (!dbus_proxy())
    return;

  LOG(INFO) << "Register suspend delay of " << timeout.InMilliseconds()
            << " ms.";
  power_manager::RegisterSuspendDelayRequest request_proto;
  request_proto.set_timeout(timeout.ToInternalValue());
  request_proto.set_description(description);
  vector<uint8_t> serialized_request;
  CHECK(SerializeProtocolBuffer(request_proto, &serialized_request));

  vector<uint8_t> serialized_reply;
  try {
    serialized_reply = dbus_proxy()->RegisterSuspendDelay(serialized_request);
  } catch (const DBus::Error &error) {
    LOG(ERROR) << "Failed to register suspend delay. DBus exception: "
               << error.name() << ": " << error.what();
    return;
  }

  power_manager::RegisterSuspendDelayReply reply_proto;
  if (!DeserializeProtocolBuffer(serialized_reply, &reply_proto)) {
    LOG(ERROR) << "Failed to register suspend delay.  Couldn't parse response.";
    return;
  }
  suspend_delay_registered_ = true;
  suspend_delay_id_ = reply_proto.delay_id();
}

void PowerManager::UnregisterSuspendDelay() {
  if (!suspend_delay_registered_)
    return;

  if (!dbus_proxy()) {
    suspend_delay_registered_ = false;
    return;
  }

  LOG(INFO) << "Calling UnregisterSuspendDelay (" << suspend_delay_id_ << ")";
  power_manager::UnregisterSuspendDelayRequest request_proto;
  request_proto.set_delay_id(suspend_delay_id_);
  vector<uint8_t> serialized_request;
  CHECK(SerializeProtocolBuffer(request_proto, &serialized_request));

  try {
    dbus_proxy()->UnregisterSuspendDelay(serialized_request);
    suspend_delay_registered_ = false;
    suspend_delay_id_ = 0;
  } catch (const DBus::Error &error) {
    LOG(ERROR) << "Failed to unregister suspend delay. DBus exception: "
               << error.name() << ": " << error.what();
  }
}

void PowerManager::OnSuspendImminent(const vector<uint8_t> &serialized_proto) {
  power_manager::SuspendImminent proto;
  if (!DeserializeProtocolBuffer(serialized_proto, &proto)) {
    LOG(ERROR) << "Failed to parse SuspendImminent signal.";
    return;
  }

  LOG(INFO) << "Received SuspendImminent (" << proto.suspend_id() << ").";
  if (!suspended_) {
    wimax_manager_->Suspend();
    suspended_ = true;
  }
  SendHandleSuspendReadiness(proto.suspend_id());
  // If the power manager does not emit a SuspendDone signal within
  // |kSuspendTimeoutInSeconds|, assume suspend is canceled. Schedule a callback
  // to resume.
  suspend_timeout_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromSeconds(kSuspendTimeoutInSeconds),
      this,
      &PowerManager::ResumeOnSuspendTimedOut);
}

void PowerManager::OnSuspendDone(const vector<uint8_t> &serialized_proto) {
  power_manager::SuspendDone proto;
  if (!DeserializeProtocolBuffer(serialized_proto, &proto)) {
    LOG(ERROR) << "Failed to parse SuspendDone signal.";
    return;
  }

  LOG(INFO) << "Received SuspendDone (" << proto.suspend_id() << ").";
  HandleResume();
}

void PowerManager::SendHandleSuspendReadiness(int suspend_id) {
  LOG(INFO) << "Calling HandleSuspendReadiness (" << suspend_id << ").";
  power_manager::SuspendReadinessInfo proto;
  proto.set_delay_id(suspend_delay_id_);
  proto.set_suspend_id(suspend_id);
  vector<uint8_t> serialized_proto;
  CHECK(SerializeProtocolBuffer(proto, &serialized_proto));

  try {
    dbus_proxy()->HandleSuspendReadiness(serialized_proto);
  } catch (const DBus::Error &error) {
    LOG(ERROR) << "Failed to call HandleSuspendReadiness. DBus exception: "
               << error.name() << ": " << error.what();
  }
}

void PowerManager::ResumeOnSuspendTimedOut() {
  LOG(WARNING) << "Timed out waiting for SuspendDone signal from "
               << "power manager. Assuming suspend was canceled.";
  HandleResume();
}

void PowerManager::HandleResume() {
  suspend_timeout_timer_.Stop();
  if (suspended_) {
    wimax_manager_->Resume();
    suspended_ = false;
  }
}

}  // namespace wimax_manager
