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

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/command_line.h>
#include <base/logging.h>
#include <base/memory/scoped_refptr.h>
#include <base/message_loop/message_pump_type.h>
#include <base/optional.h>
#include <base/run_loop.h>
#include <base/task/single_thread_task_executor.h>
#include <base/threading/thread_task_runner_handle.h>
#include <base/time/time.h>
#include <brillo/flag_helper.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>

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

namespace {

// Passes |request| to powerd's |method_name| D-Bus method.
// Copies the returned protocol buffer to |reply_out|, which may be NULL if no
// reply is expected.
bool CallMethod(dbus::ObjectProxy* powerd_proxy,
                const std::string& method_name,
                const google::protobuf::MessageLite& request,
                google::protobuf::MessageLite* reply_out) {
  LOG(INFO) << "Calling " << method_name << " method";
  dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
                               method_name);
  dbus::MessageWriter writer(&method_call);
  writer.AppendProtoAsArrayOfBytes(request);

  std::unique_ptr<dbus::Response> response(powerd_proxy->CallMethodAndBlock(
      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
  if (!response)
    return false;
  if (!reply_out)
    return true;

  dbus::MessageReader reader(response.get());
  CHECK(reader.PopArrayOfBytesAsProto(reply_out))
      << "Unable to parse response from call to " << method_name;
  return true;
}

// Human-readable description of the delay's purpose.
const char kSuspendDelayDescription[] = "suspend_delay_sample";

}  // namespace

class SuspendDelayRegisterer {
 public:
  SuspendDelayRegisterer(int delay_ms, int timeout_ms, bool dark_suspend_delay)
      : delay_ms_(delay_ms),
        timeout_ms_(timeout_ms),
        dark_suspend_delay_(dark_suspend_delay),
        weak_ptr_factory_(this) {
    dbus::Bus::Options options;
    options.bus_type = dbus::Bus::SYSTEM;
    bus_ = new dbus::Bus(options);
    CHECK(bus_->Connect());
    powerd_proxy_ = bus_->GetObjectProxy(
        power_manager::kPowerManagerServiceName,
        dbus::ObjectPath(power_manager::kPowerManagerServicePath));
    RegisterSuspendDelay();
    powerd_proxy_->SetNameOwnerChangedCallback(
        base::Bind(&SuspendDelayRegisterer::NameOwnerChangedReceived,
                   weak_ptr_factory_.GetWeakPtr()));
  }
  SuspendDelayRegisterer(const SuspendDelayRegisterer&) = delete;
  SuspendDelayRegisterer& operator=(const SuspendDelayRegisterer&) = delete;

 private:
  // Announces that the process is ready for suspend attempt |suspend_id|.
  void SendSuspendReady(int suspend_id) {
    CHECK(delay_id_) << "Invalid suspend delay Id";
    LOG(INFO) << "Announcing readiness of delay " << delay_id_.value()
              << " for suspend attempt " << suspend_id;
    power_manager::SuspendReadinessInfo request;
    request.set_delay_id(delay_id_.value());
    request.set_suspend_id(suspend_id);
    CallMethod(powerd_proxy_, power_manager::kHandleSuspendReadinessMethod,
               request, nullptr);
  }

  // Handles the start of a suspend attempt. Posts a task to run
  // SendSuspendReady() after a delay.
  void HandleSuspendImminent(dbus::Signal* signal) {
    power_manager::SuspendImminent info;
    dbus::MessageReader reader(signal);
    CHECK(reader.PopArrayOfBytesAsProto(&info));
    int suspend_id = info.suspend_id();

    LOG(INFO) << "Got notification about suspend attempt " << suspend_id;
    LOG(INFO) << "Sleeping " << delay_ms_ << " ms before responding";
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&SuspendDelayRegisterer::SendSuspendReady,
                   weak_ptr_factory_.GetWeakPtr(), suspend_id),
        base::TimeDelta::FromMilliseconds(delay_ms_));
  }

  // Handles the completion of a suspend attempt.
  void HandleSuspendDone(dbus::Signal* signal) {
    power_manager::SuspendDone info;
    dbus::MessageReader reader(signal);
    CHECK(reader.PopArrayOfBytesAsProto(&info));
    const base::TimeDelta duration =
        base::TimeDelta::FromInternalValue(info.suspend_duration());
    LOG(INFO) << "Suspend attempt " << info.suspend_id() << " is complete; "
              << "system was suspended for " << duration.InMilliseconds()
              << " ms";
  }

  // Handles the result of an attempt to connect to a D-Bus signal.
  void DBusSignalConnected(const std::string& interface,
                           const std::string& signal,
                           bool success) {
    CHECK(success) << "Unable to connect to " << interface << "." << signal;
  }

  // Registers a suspend delay and returns the corresponding ID.
  void RegisterSuspendDelay() {
    power_manager::RegisterSuspendDelayRequest request;
    request.set_timeout(
        base::TimeDelta::FromMilliseconds(timeout_ms_).ToInternalValue());
    request.set_description(kSuspendDelayDescription);
    std::string method_name =
        dark_suspend_delay_ ? power_manager::kRegisterDarkSuspendDelayMethod
                            : power_manager::kRegisterSuspendDelayMethod;
    power_manager::RegisterSuspendDelayReply reply;
    CHECK(CallMethod(powerd_proxy_, method_name, request, &reply));
    LOG(INFO) << "Registered " << (dark_suspend_delay_ ? "dark " : "")
              << "suspend delay " << reply.delay_id();
    delay_id_ = reply.delay_id();

    powerd_proxy_->ConnectToSignal(
        power_manager::kPowerManagerInterface,
        power_manager::kSuspendImminentSignal,
        base::Bind(&SuspendDelayRegisterer::HandleSuspendImminent,
                   weak_ptr_factory_.GetWeakPtr()),
        base::Bind(&SuspendDelayRegisterer::DBusSignalConnected,
                   weak_ptr_factory_.GetWeakPtr()));
    powerd_proxy_->ConnectToSignal(
        power_manager::kPowerManagerInterface,
        power_manager::kSuspendDoneSignal,
        base::Bind(&SuspendDelayRegisterer::HandleSuspendDone,
                   weak_ptr_factory_.GetWeakPtr()),
        base::Bind(&SuspendDelayRegisterer::DBusSignalConnected,
                   weak_ptr_factory_.GetWeakPtr()));
  }

  void NameOwnerChangedReceived(const std::string& old_owner,
                                const std::string& new_owner) {
    //  Try to register suspend delay only if available.
    if (!new_owner.empty()) {
      LOG(INFO) << "Received NameOwnerChanged d-bus signal.";
      RegisterSuspendDelay();
    }
  }

  int delay_ms_;
  int timeout_ms_;
  // Id assigned by powerd to a suspend delay client.
  base::Optional<int> delay_id_;
  // Whether to register dark/full suspend delay.
  bool dark_suspend_delay_ = false;
  scoped_refptr<dbus::Bus> bus_;
  dbus::ObjectProxy* powerd_proxy_ = nullptr;

  base::WeakPtrFactory<SuspendDelayRegisterer> weak_ptr_factory_;
};

int main(int argc, char* argv[]) {
  DEFINE_int32(delay_ms, 5000,
               "Milliseconds to wait before reporting suspend readiness");
  DEFINE_int32(timeout_ms, 7000, "Suspend timeout in milliseconds");
  DEFINE_bool(dark_suspend, false, "Register delay as a dark suspend");

  brillo::FlagHelper::Init(
      argc, argv,
      "Exercise powerd's functionality that permits other processes to\n"
      "perform last-minute work before the system suspends.");
  base::AtExitManager at_exit_manager;
  base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::IO);

  SuspendDelayRegisterer suspend_delay_registerer(
      FLAGS_delay_ms, FLAGS_timeout_ms, FLAGS_dark_suspend);
  base::RunLoop().Run();

  // powerd will automatically unregister this process's suspend delay when the
  // process disconnects from D-Bus.
  return 0;
}
