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

// This is a sample daemon that "handles" Buffet commands.
// It just prints the information about the command received to stdout and
// marks the command as processed.

#include <string>
#include <sysexits.h>

#include <base/bind.h>
#include <base/command_line.h>
#include <base/format_macros.h>
#include <base/json/json_writer.h>
#include <base/values.h>
#include <chromeos/daemons/dbus_daemon.h>
#include <chromeos/map_utils.h>
#include <chromeos/strings/string_utils.h>
#include <chromeos/syslog_logging.h>

#include "buffet/dbus-proxies.h"

namespace {
const char kTestCommandCategory[] = "test";

std::unique_ptr<base::DictionaryValue> DictionaryToJson(
    const chromeos::VariantDictionary& dictionary);

std::unique_ptr<base::Value> AnyToJson(const chromeos::Any& value) {
  if (value.IsTypeCompatible<chromeos::VariantDictionary>())
    return DictionaryToJson(value.Get<chromeos::VariantDictionary>());

  if (value.IsTypeCompatible<std::string>()) {
    return std::unique_ptr<base::Value>{
        new base::StringValue(value.Get<std::string>())};
  }

  if (value.IsTypeCompatible<double>()) {
    return std::unique_ptr<base::Value>{
        new base::FundamentalValue(value.Get<double>())};
  }

  if (value.IsTypeCompatible<bool>()) {
    return std::unique_ptr<base::Value>{
        new base::FundamentalValue(value.Get<bool>())};
  }

  if (value.IsTypeCompatible<int>()) {
    return std::unique_ptr<base::Value>{
        new base::FundamentalValue(value.Get<int>())};
  }

  LOG(FATAL) << "Unsupported type:" << value.GetType().name();
  return {};
}

std::unique_ptr<base::DictionaryValue> DictionaryToJson(
    const chromeos::VariantDictionary& dictionary) {
  std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};
  for (const auto& it : dictionary)
    result->Set(it.first, AnyToJson(it.second).release());
  return result;
}

std::string DictionaryToString(const chromeos::VariantDictionary& dictionary) {
  std::unique_ptr<base::DictionaryValue> json{DictionaryToJson(dictionary)};
  std::string str;
  base::JSONWriter::Write(json.get(), &str);
  return str;
}

}  // anonymous namespace

class Daemon : public chromeos::DBusDaemon {
 public:
  Daemon() = default;

 protected:
  int OnInit() override;
  void OnShutdown(int* return_code) override;

 private:
  std::unique_ptr<org::chromium::Buffet::ObjectManagerProxy> object_manager_;

  void OnBuffetCommand(org::chromium::Buffet::CommandProxy* command);
  void OnBuffetCommandRemoved(const dbus::ObjectPath& object_path);
  void OnPropertyChange(org::chromium::Buffet::CommandProxy* command,
                        const std::string& property_name);
  void OnCommandProgress(org::chromium::Buffet::CommandProxy* command,
                         int progress);

  DISALLOW_COPY_AND_ASSIGN(Daemon);
};

int Daemon::OnInit() {
  int return_code = chromeos::DBusDaemon::OnInit();
  if (return_code != EX_OK)
    return return_code;

  object_manager_.reset(new org::chromium::Buffet::ObjectManagerProxy{bus_});
  object_manager_->SetCommandAddedCallback(
      base::Bind(&Daemon::OnBuffetCommand, base::Unretained(this)));
  object_manager_->SetCommandRemovedCallback(
      base::Bind(&Daemon::OnBuffetCommandRemoved, base::Unretained(this)));

  printf("Waiting for commands...\n");
  return EX_OK;
}

void Daemon::OnShutdown(int* return_code) {
  printf("Shutting down...\n");
}

void Daemon::OnPropertyChange(org::chromium::Buffet::CommandProxy* command,
                              const std::string& property_name) {
  printf("Notification: property '%s' on command '%s' changed.\n",
         property_name.c_str(), command->id().c_str());
  printf("  Current command status: '%s'\n", command->status().c_str());
  std::string progress = DictionaryToString(command->progress());
  printf("  Current command progress: %s\n", progress.c_str());
  std::string results = DictionaryToString(command->results());
  printf("  Current command results: %s\n", results.c_str());
}

void Daemon::OnBuffetCommand(org::chromium::Buffet::CommandProxy* command) {
  // "Handle" only commands that belong to this daemon's category.
  if (command->category() != kTestCommandCategory ||
      command->status() == "done") {
    return;
  }

  command->SetPropertyChangedCallback(base::Bind(&Daemon::OnPropertyChange,
                                                 base::Unretained(this)));
  printf("++++++++++++++++++++++++++++++++++++++++++++++++\n");
  printf("Command received: %s\n", command->name().c_str());
  printf("DBus Object Path: %s\n", command->GetObjectPath().value().c_str());
  printf("        category: %s\n", command->category().c_str());
  printf("              ID: %s\n", command->id().c_str());
  printf("          status: %s\n", command->status().c_str());
  printf("          origin: %s\n", command->origin().c_str());
  std::string param_names = DictionaryToString(command->parameters());
  printf(" parameters: %s\n", param_names.c_str());
  OnCommandProgress(command, 0);
}

void Daemon::OnCommandProgress(org::chromium::Buffet::CommandProxy* command,
                               int progress) {
  printf("Updating command '%s' progress to %d%%\n", command->id().c_str(),
         progress);
  auto new_progress = command->progress();
  new_progress["progress"] = progress;
  command->SetProgress(new_progress, nullptr);

  if (progress >= 100) {
    command->Done(nullptr);
  } else {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, base::Bind(&Daemon::OnCommandProgress,
                              base::Unretained(this), command, progress + 10),
        base::TimeDelta::FromSeconds(1));
  }
}

void Daemon::OnBuffetCommandRemoved(const dbus::ObjectPath& object_path) {
  printf("------------------------------------------------\n");
  printf("Command removed\n");
  printf("DBus Object Path: %s\n", object_path.value().c_str());
}

int main(int argc, char* argv[]) {
  base::CommandLine::Init(argc, argv);
  chromeos::InitLog(chromeos::kLogToSyslog |
                    chromeos::kLogToStderr |
                    chromeos::kLogHeader);
  Daemon daemon;
  return daemon.Run();
}
