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

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

#include "shill/logging.h"
#include "shill/proto_bindings/power_manager/suspend.pb.h"

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

namespace shill {

namespace {

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

PowerManagerProxy::PowerManagerProxy(PowerManagerProxyDelegate *delegate,
                                     DBus::Connection *connection)
    : proxy_(delegate, connection) {}

PowerManagerProxy::~PowerManagerProxy() {}

bool PowerManagerProxy::RegisterSuspendDelay(base::TimeDelta timeout,
                                             int *delay_id_out) {
  LOG(INFO) << __func__ << "(" << timeout.InMilliseconds() << ")";

  power_manager::RegisterSuspendDelayRequest request_proto;
  request_proto.set_timeout(timeout.ToInternalValue());
  vector<uint8_t> serialized_request;
  CHECK(SerializeProtocolBuffer(request_proto, &serialized_request));

  vector<uint8_t> serialized_reply;
  try {
    serialized_reply = proxy_.RegisterSuspendDelay(serialized_request);
  } catch (const DBus::Error &e) {
    LOG(ERROR) << "DBus exception: " << e.name() << ": " << e.what();
    return false;
  }

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

bool PowerManagerProxy::UnregisterSuspendDelay(int delay_id) {
  LOG(INFO) << __func__ << "(" << delay_id << ")";

  power_manager::UnregisterSuspendDelayRequest request_proto;
  request_proto.set_delay_id(delay_id);
  vector<uint8_t> serialized_request;
  CHECK(SerializeProtocolBuffer(request_proto, &serialized_request));

  try {
    proxy_.UnregisterSuspendDelay(serialized_request);
    return true;
  } catch (const DBus::Error &e) {
    LOG(ERROR) << "DBus exception: " << e.name() << ": " << e.what();
    return false;
  }
}

bool PowerManagerProxy::ReportSuspendReadiness(int delay_id, int suspend_id) {
  LOG(INFO) << __func__  << "(" << delay_id << ", " << suspend_id << ")";

  power_manager::SuspendReadinessInfo proto;
  proto.set_delay_id(delay_id);
  proto.set_suspend_id(suspend_id);
  vector<uint8_t> serialized_proto;
  CHECK(SerializeProtocolBuffer(proto, &serialized_proto));

  try {
    proxy_.HandleSuspendReadiness(serialized_proto);
    return true;
  } catch (const DBus::Error &e) {
    LOG(ERROR) << "DBus exception: " << e.name() << ": " << e.what();
    return false;
  }
}

PowerManagerProxy::Proxy::Proxy(PowerManagerProxyDelegate *delegate,
                                DBus::Connection *connection)
    : DBus::ObjectProxy(*connection,
                        power_manager::kPowerManagerServicePath,
                        power_manager::kPowerManagerServiceName),
      delegate_(delegate) {}

PowerManagerProxy::Proxy::~Proxy() {}

void PowerManagerProxy::Proxy::SuspendImminent(
    const vector<uint8_t> &serialized_proto) {
  LOG(INFO) << __func__;

  power_manager::SuspendImminent proto;
  if (!DeserializeProtocolBuffer(serialized_proto, &proto)) {
    LOG(ERROR) << "Failed to parse SuspendImminent signal.";
    return;
  }
  delegate_->OnSuspendImminent(proto.suspend_id());
}

void PowerManagerProxy::Proxy::PowerStateChanged(
    const string &new_power_state) {
  LOG(INFO) << __func__ << "(" << new_power_state << ")";

  PowerManagerProxyDelegate::SuspendState suspend_state;
  if (new_power_state == "on") {
    suspend_state = PowerManagerProxyDelegate::kOn;
  } else if (new_power_state == "standby") {
    suspend_state = PowerManagerProxyDelegate::kStandby;
  } else if (new_power_state == "mem") {
    suspend_state = PowerManagerProxyDelegate::kMem;
  } else if (new_power_state == "disk") {
    suspend_state = PowerManagerProxyDelegate::kDisk;
  } else {
    suspend_state = PowerManagerProxyDelegate::kUnknown;
  }
  delegate_->OnPowerStateChanged(suspend_state);
}

}  // namespace shill
