// 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/values.h>
#include <chromeos/any.h>
#include <chromeos/data_encoding.h>
#include <chromeos/dbus/data_serialization.h>
#include <chromeos/dbus/dbus_method_invoker.h>
#include <chromeos/errors/error.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/libbuffet/dbus_constants.h"

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

using chromeos::dbus_utils::CallMethodAndBlock;
using chromeos::dbus_utils::CallMethodAndBlockWithTimeout;
using chromeos::dbus_utils::Dictionary;
using chromeos::dbus_utils::ExtractMethodCallResults;
using chromeos::ErrorPtr;

namespace {

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
                    << " prop_name prop_value" << 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();

    ErrorPtr error;
    auto response = CallMethodAndBlock(
        manager_proxy_,
        kManagerInterface, kManagerTestMethod, &error,
        message);
    std::string response_message;
    if (!response ||
        !ExtractMethodCallResults(response.get(), &error, &response_message)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << std::endl;
      return EX_UNAVAILABLE;
    }

    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;
    }

    ErrorPtr error;
    auto response = CallMethodAndBlock(
        manager_proxy_,
        kManagerInterface, kManagerCheckDeviceRegistered, &error);
    std::string device_id;
    if (!response ||
        !ExtractMethodCallResults(response.get(), &error, &device_id)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << std::endl;
      return EX_UNAVAILABLE;
    }

    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;
    }

    ErrorPtr error;
    auto response = CallMethodAndBlock(
        manager_proxy_, kManagerInterface, kManagerGetDeviceInfo, &error);
    std::string device_info;
    if (!response ||
        !ExtractMethodCallResults(response.get(), &error, &device_info)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << std::endl;
      return EX_UNAVAILABLE;
    }

    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;
    }

    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)));
      }
    }

    ErrorPtr error;
    static const int timeout_ms = 3000;
    auto response = CallMethodAndBlockWithTimeout(
        timeout_ms,
        manager_proxy_,
        kManagerInterface, kManagerStartRegisterDevice, &error,
        params);
    std::string info;
    if (!response ||
        !ExtractMethodCallResults(response.get(), &error, &info)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << std::endl;
      return EX_UNAVAILABLE;
    }

    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;
    }

    ErrorPtr error;
    std::string user_auth_code;
    if (!args.empty()) { user_auth_code = args.front(); }
    static const int timeout_ms = 10000;
    auto response = CallMethodAndBlockWithTimeout(
        timeout_ms,
        manager_proxy_,
        kManagerInterface, kManagerFinishRegisterDevice, &error,
        user_auth_code);
    std::string device_id;
    if (!response ||
        !ExtractMethodCallResults(response.get(), &error, &device_id)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << std::endl;
      return EX_UNAVAILABLE;
    }

    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() != 2) {
      std::cerr << "Invalid number of arguments for "
                << "Manager." << kManagerUpdateStateMethod << std::endl;
      usage();
      return EX_USAGE;
    }

    ErrorPtr error;
    Dictionary property_set{{args.front(), args.back()}};
    auto response = CallMethodAndBlock(
        manager_proxy_,
        kManagerInterface, kManagerUpdateStateMethod, &error,
        property_set);
    if (!response || !ExtractMethodCallResults(response.get(), &error)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << 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;
    }

    ErrorPtr error;
    auto response = CallMethodAndBlock(
        manager_proxy_,
        kManagerInterface, kManagerAddCommand, &error,
        args.front());
    if (!response || !ExtractMethodCallResults(response.get(), &error)) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << 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;
    }

    ErrorPtr error;
    auto response = CallMethodAndBlock(
        manager_proxy_,
        dbus::kObjectManagerInterface, dbus::kObjectManagerGetManagedObjects,
        &error);
    if (!response) {
      std::cout << "Failed to receive a response:"
                << error->GetMessage() << 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;
}
