// Copyright 2014 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 <iostream>  // NOLINT(readability/streams)
#include <memory>
#include <string>
#include <sysexits.h>

#include <base/command_line.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/memory/scoped_ptr.h>
#include <base/values.h>
#include <chromeos/any.h>
#include <chromeos/data_encoding.h>
#include <chromeos/dbus/data_serialization.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
#include <dbus/object_manager.h>
#include <dbus/values_util.h>

#include "buffet/dbus_constants.h"

using namespace buffet::dbus_constants;  // NOLINT(build/namespaces)

namespace {
static const int default_timeout_ms = 1000;

void usage() {
  std::cerr << "Possible commands:" << std::endl;
  std::cerr << "  " << kManagerTestMethod << " <message>" << std::endl;
  std::cerr << "  " << kManagerCheckDeviceRegistered << std::endl;
  std::cerr << "  " << kManagerGetDeviceInfo << std::endl;
  std::cerr << "  " << kManagerStartRegisterDevice
                    << " param1 = val1&param2 = val2..." << std::endl;
  std::cerr << "  " << kManagerFinishRegisterDevice
                    << " device_id" << std::endl;
  std::cerr << "  " << kManagerAddCommand
                    << " '{\"name\":\"command_name\",\"parameters\":{}}'"
                    << std::endl;
  std::cerr << "  " << kManagerUpdateStateMethod << std::endl;
  std::cerr << "  " << dbus::kObjectManagerGetManagedObjects << std::endl;
}

class BuffetHelperProxy {
 public:
  int Init() {
    dbus::Bus::Options options;
    options.bus_type = dbus::Bus::SYSTEM;
    bus_ = new dbus::Bus(options);
    manager_proxy_ = bus_->GetObjectProxy(
        kServiceName,
        dbus::ObjectPath(kManagerServicePath));
    root_proxy_ = bus_->GetObjectProxy(
        kServiceName,
        dbus::ObjectPath(kRootServicePath));
    return EX_OK;
  }

  int CallTestMethod(const CommandLine::StringVector& args) {
    std::string message;
    if (!args.empty())
      message = args.front();

    dbus::MethodCall method_call(kManagerInterface, kManagerTestMethod);
    dbus::MessageWriter writer(&method_call);
    writer.AppendString(message);
    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, default_timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }
    dbus::MessageReader reader(response.get());
    std::string response_message;
    if (!reader.PopString(&response_message)) {
      std::cout << "No valid response." << std::endl;
      return EX_SOFTWARE;
    }
    std::cout << "Received a response: " << response_message << std::endl;
    return EX_OK;
  }

  int CallManagerCheckDeviceRegistered(const CommandLine::StringVector& args) {
    if (!args.empty()) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerCheckDeviceRegistered << std::endl;
      usage();
      return EX_USAGE;
    }
    dbus::MethodCall method_call(
        kManagerInterface, kManagerCheckDeviceRegistered);

    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, default_timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }

    dbus::MessageReader reader(response.get());
    std::string device_id;
    if (!reader.PopString(&device_id)) {
      std::cout << "No device ID in response." << std::endl;
      return EX_SOFTWARE;
    }

    std::cout << "Device ID: "
              << (device_id.empty() ? std::string("<unregistered>") : device_id)
              << std::endl;
    return EX_OK;
  }

  int CallManagerGetDeviceInfo(const CommandLine::StringVector& args) {
    if (!args.empty()) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerGetDeviceInfo << std::endl;
      usage();
      return EX_USAGE;
    }
    dbus::MethodCall method_call(
        kManagerInterface, kManagerGetDeviceInfo);

    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, default_timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }

    dbus::MessageReader reader(response.get());
    std::string device_info;
    if (!reader.PopString(&device_info)) {
      std::cout << "No device info in response." << std::endl;
      return EX_SOFTWARE;
    }

    std::cout << "Device Info: "
      << (device_info.empty() ? std::string("<unregistered>") : device_info)
      << std::endl;
    return EX_OK;
  }

  int CallManagerStartRegisterDevice(const CommandLine::StringVector& args) {
    if (args.size() > 1) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerStartRegisterDevice << std::endl;
      usage();
      return EX_USAGE;
    }
    chromeos::dbus_utils::Dictionary params;

    if (!args.empty()) {
      auto key_values = chromeos::data_encoding::WebParamsDecode(args.front());
      for (const auto& pair : key_values) {
        params.insert(std::make_pair(pair.first, chromeos::Any(pair.second)));
      }
    }

    dbus::MethodCall method_call(
        kManagerInterface, kManagerStartRegisterDevice);
    dbus::MessageWriter writer(&method_call);
    CHECK(chromeos::dbus_utils::AppendValueToWriter(&writer, params))
        << "Failed to send the parameters over D-Bus";

    static const int timeout_ms = 3000;
    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }

    dbus::MessageReader reader(response.get());
    std::string info;
    if (!reader.PopString(&info)) {
      std::cout << "No valid response." << std::endl;
      return EX_SOFTWARE;
    }

    std::cout << "Registration started: " << info << std::endl;
    return EX_OK;
  }

  int CallManagerFinishRegisterDevice(const CommandLine::StringVector& args) {
    if (args.size() > 1) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerFinishRegisterDevice << std::endl;
      usage();
      return EX_USAGE;
    }
    dbus::MethodCall method_call(
        kManagerInterface, kManagerFinishRegisterDevice);
    dbus::MessageWriter writer(&method_call);
    std::string user_auth_code;
    if (!args.empty()) { user_auth_code = args.front(); }
    writer.AppendString(user_auth_code);
    static const int timeout_ms = 10000;
    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }

    dbus::MessageReader reader(response.get());
    std::string device_id;
    if (!reader.PopString(&device_id)) {
      std::cout << "No device ID in response." << std::endl;
      return EX_SOFTWARE;
    }

    std::cout << "Device ID is "
              << (device_id.empty() ? std::string("<unregistered>") : device_id)
              << std::endl;
    return EX_OK;
  }

  int CallManagerUpdateState(const CommandLine::StringVector& args) {
    if (args.size() != 1) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerUpdateStateMethod << std::endl;
      usage();
      return EX_USAGE;
    }
    dbus::MethodCall method_call(
        kManagerInterface, kManagerUpdateStateMethod);
    dbus::MessageWriter writer(&method_call);
    writer.AppendString(args.front());
    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, default_timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }
    return EX_OK;
  }

  int CallManagerAddCommand(const CommandLine::StringVector& args) {
    if (args.size() != 1) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerAddCommand << std::endl;
      usage();
      return EX_USAGE;
    }
    dbus::MethodCall method_call(
        kManagerInterface, kManagerAddCommand);
    dbus::MessageWriter writer(&method_call);
    writer.AppendString(args.front());
    scoped_ptr<dbus::Response> response(
        manager_proxy_->CallMethodAndBlock(&method_call, default_timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }
    return EX_OK;
  }

  int CallRootGetManagedObjects(const CommandLine::StringVector& args) {
    if (!args.empty()) {
      std::cerr << "Invalid number of arguments for "
                << dbus::kObjectManagerGetManagedObjects << std::endl;
      usage();
      return EX_USAGE;
    }
    dbus::MethodCall method_call(
        dbus::kObjectManagerInterface, dbus::kObjectManagerGetManagedObjects);
    scoped_ptr<dbus::Response> response(
        root_proxy_->CallMethodAndBlock(&method_call, default_timeout_ms));
    if (!response) {
      std::cout << "Failed to receive a response." << std::endl;
      return EX_UNAVAILABLE;
    }
    std::cout << response->ToString() << std::endl;
    return EX_OK;
  }

 private:
  scoped_refptr<dbus::Bus> bus_;
  dbus::ObjectProxy* manager_proxy_{nullptr};
  dbus::ObjectProxy* root_proxy_{nullptr};
};

}  // namespace

int main(int argc, char** argv) {
  CommandLine::Init(argc, argv);
  CommandLine* cl = CommandLine::ForCurrentProcess();
  CommandLine::StringVector args = cl->GetArgs();
  if (args.empty()) {
    usage();
    return EX_USAGE;
  }

  // Pop the command off of the args list.
  std::string command = args.front();
  args.erase(args.begin());
  int err = EX_USAGE;
  BuffetHelperProxy helper;
  err = helper.Init();
  if (err) {
    std::cerr << "Error initializing proxies." << std::endl;
    return err;
  }

  if (command.compare(kManagerTestMethod) == 0) {
    err = helper.CallTestMethod(args);
  } else if (command.compare(kManagerCheckDeviceRegistered) == 0 ||
             command.compare("cr") == 0) {
    err = helper.CallManagerCheckDeviceRegistered(args);
  } else if (command.compare(kManagerGetDeviceInfo) == 0 ||
             command.compare("di") == 0) {
    err = helper.CallManagerGetDeviceInfo(args);
  } else if (command.compare(kManagerStartRegisterDevice) == 0 ||
             command.compare("sr") == 0) {
    err = helper.CallManagerStartRegisterDevice(args);
  } else if (command.compare(kManagerFinishRegisterDevice) == 0 ||
             command.compare("fr") == 0) {
    err = helper.CallManagerFinishRegisterDevice(args);
  } else if (command.compare(kManagerUpdateStateMethod) == 0 ||
             command.compare("us") == 0) {
    err = helper.CallManagerUpdateState(args);
  } else if (command.compare(kManagerAddCommand) == 0 ||
             command.compare("ac") == 0) {
    err = helper.CallManagerAddCommand(args);
  } else if (command.compare(dbus::kObjectManagerGetManagedObjects) == 0) {
    err = helper.CallRootGetManagedObjects(args);
  } else {
    std::cerr << "Unknown command: " << command << std::endl;
    usage();
  }

  if (err) {
    std::cerr << "Done, with errors." << std::endl;
  } else {
    std::cout << "Done." << std::endl;
  }
  return err;
}
