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

#include <map>
#include <string>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/json/json_writer.h>
#include <dbus/bus.h>
#include <dbus/object_path.h>
#include <dbus/values_util.h>

#include "buffet/async_event_sequencer.h"
#include "buffet/dbus_constants.h"
#include "buffet/dbus_utils.h"
#include "buffet/error.h"
#include "buffet/exported_object_manager.h"

using buffet::dbus_utils::AsyncEventSequencer;
using buffet::dbus_utils::GetBadArgsError;
using buffet::dbus_utils::GetDBusError;

namespace buffet {

Manager::Manager(
    scoped_refptr<dbus::Bus> bus,
    base::WeakPtr<dbus_utils::ExportedObjectManager> object_manager)
    : bus_(bus),
      exported_object_(bus->GetExportedObject(
          dbus::ObjectPath(dbus_constants::kManagerServicePath))),
      object_manager_(object_manager) { }

Manager::~Manager() {
  object_manager_->ReleaseInterface(
      dbus::ObjectPath(dbus_constants::kManagerServicePath),
      dbus_constants::kManagerInterface);
  // Prevent the properties object from making calls to the exported object.
  properties_.reset(nullptr);
  // Unregister ourselves from the Bus.  This prevents the bus from calling
  // our callbacks in between the Manager's death and the bus unregistering
  // our exported object on shutdown.  Unretained makes no promises of memory
  // management.
  exported_object_->Unregister();
  exported_object_ = nullptr;
}

void Manager::Init(const OnInitFinish& cb) {
  scoped_refptr<AsyncEventSequencer> sequencer(
      new AsyncEventSequencer());
  exported_object_->ExportMethod(
      dbus_constants::kManagerInterface,
      dbus_constants::kManagerCheckDeviceRegistered,
      dbus_utils::GetExportableDBusMethod(
          base::Bind(&Manager::HandleCheckDeviceRegistered,
          base::Unretained(this))),
      sequencer->GetExportHandler(
          dbus_constants::kManagerInterface,
          dbus_constants::kManagerCheckDeviceRegistered,
          "Failed exporting CheckDeviceRegistered method",
          true));
  exported_object_->ExportMethod(
      dbus_constants::kManagerInterface,
      dbus_constants::kManagerGetDeviceInfo,
      dbus_utils::GetExportableDBusMethod(
          base::Bind(&Manager::HandleGetDeviceInfo,
          base::Unretained(this))),
      sequencer->GetExportHandler(
          dbus_constants::kManagerInterface,
          dbus_constants::kManagerGetDeviceInfo,
          "Failed exporting GetDeviceInfo method",
          true));
  exported_object_->ExportMethod(
      dbus_constants::kManagerInterface,
      dbus_constants::kManagerStartRegisterDevice,
      dbus_utils::GetExportableDBusMethod(
          base::Bind(&Manager::HandleStartRegisterDevice,
          base::Unretained(this))),
      sequencer->GetExportHandler(
          dbus_constants::kManagerInterface,
          dbus_constants::kManagerStartRegisterDevice,
          "Failed exporting StartRegisterDevice method",
          true));
  exported_object_->ExportMethod(
      dbus_constants::kManagerInterface,
      dbus_constants::kManagerFinishRegisterDevice,
      dbus_utils::GetExportableDBusMethod(
          base::Bind(&Manager::HandleFinishRegisterDevice,
          base::Unretained(this))),
      sequencer->GetExportHandler(
          dbus_constants::kManagerInterface,
          dbus_constants::kManagerFinishRegisterDevice,
          "Failed exporting FinishRegisterDevice method",
          true));
  exported_object_->ExportMethod(
      dbus_constants::kManagerInterface,
      dbus_constants::kManagerUpdateStateMethod,
      dbus_utils::GetExportableDBusMethod(
          base::Bind(&Manager::HandleUpdateState,
          base::Unretained(this))),
      sequencer->GetExportHandler(
          dbus_constants::kManagerInterface,
          dbus_constants::kManagerUpdateStateMethod,
          "Failed exporting UpdateState method",
          true));
  exported_object_->ExportMethod(
      dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
      dbus_utils::GetExportableDBusMethod(
          base::Bind(&Manager::HandleTestMethod, base::Unretained(this))),
      sequencer->GetExportHandler(
          dbus_constants::kManagerInterface, dbus_constants::kManagerTestMethod,
          "Failed exporting TestMethod method",
          true));
  properties_.reset(new Properties(bus_));
  // TODO(wiley): Initialize all properties appropriately before claiming
  //              the properties interface.
  properties_->state_.SetValue("{}");
  properties_->Init(
      sequencer->GetHandler("Manager properties export failed.", true));
  auto claim_interface_task = sequencer->WrapCompletionTask(
      base::Bind(&dbus_utils::ExportedObjectManager::ClaimInterface,
                 object_manager_->AsWeakPtr(),
                 dbus::ObjectPath(dbus_constants::kManagerServicePath),
                 dbus_constants::kManagerInterface,
                 properties_->GetPropertyWriter(
                     dbus_constants::kManagerInterface)));
  sequencer->OnAllTasksCompletedCall({claim_interface_task, cb});
  device_info_.Load();
}

scoped_ptr<dbus::Response> Manager::HandleCheckDeviceRegistered(
    dbus::MethodCall* method_call) {
  // Read the parameters to the method.
  dbus::MessageReader reader(method_call);
  if (reader.HasMoreData()) {
    return GetBadArgsError(method_call,
                           "Too many parameters to CheckDeviceRegistered");
  }

  LOG(INFO) << "Received call to Manager.CheckDeviceRegistered()";

  buffet::ErrorPtr error;
  bool registered = device_info_.CheckRegistration(&error);
  // If it fails due to any reason other than 'device not registered',
  // treat it as a real error and report it to the caller.
  if (!registered &&
      !error->HasError(kErrorDomainGCD, "device_not_registered")) {
    return GetDBusError(method_call, error.get());
  }

  std::string device_id;
  if (registered) {
    device_id = device_info_.GetDeviceId(&error);
    if (device_id.empty())
      return GetDBusError(method_call, error.get());
  }
  // Send back our response.
  scoped_ptr<dbus::Response> response(
      dbus::Response::FromMethodCall(method_call));
  dbus::MessageWriter writer(response.get());
  writer.AppendString(device_id);
  return response.Pass();
}

scoped_ptr<dbus::Response> Manager::HandleGetDeviceInfo(
    dbus::MethodCall* method_call) {
  // Read the parameters to the method.
  dbus::MessageReader reader(method_call);
  if (reader.HasMoreData()) {
    return GetBadArgsError(method_call,
                           "Too many parameters to GetDeviceInfo");
  }

  LOG(INFO) << "Received call to Manager.GetDeviceInfo()";

  std::string device_info_str;
  buffet::ErrorPtr error;
  auto device_info = device_info_.GetDeviceInfo(&error);
  if (!device_info)
    return GetDBusError(method_call, error.get());

  base::JSONWriter::Write(device_info.get(), &device_info_str);

  // Send back our response.
  scoped_ptr<dbus::Response> response(
      dbus::Response::FromMethodCall(method_call));
  dbus::MessageWriter writer(response.get());
  writer.AppendString(device_info_str);
  return response.Pass();
}

scoped_ptr<dbus::Response> Manager::HandleStartRegisterDevice(
    dbus::MethodCall* method_call) {
  // Read the parameters to the method.
  dbus::MessageReader reader(method_call);
  if (!reader.HasMoreData()) {
    return GetBadArgsError(method_call, "No parameters to StartRegisterDevice");
  }

  dbus::MessageReader array_reader(nullptr);
  if (!reader.PopArray(&array_reader))
    return GetBadArgsError(method_call, "Failed to read the parameter array");
  std::map<std::string, std::shared_ptr<base::Value>> params;
  while (array_reader.HasMoreData()) {
    dbus::MessageReader dict_entry_reader(nullptr);
    if (!array_reader.PopDictEntry(&dict_entry_reader))
      return GetBadArgsError(method_call, "Failed to get a call parameter");
    std::string key;
    if (!dict_entry_reader.PopString(&key))
      return GetBadArgsError(method_call, "Failed to read parameter key");
    base::Value* value = dbus::PopDataAsValue(&dict_entry_reader);
    if (!value)
      return GetBadArgsError(method_call, "Failed to read parameter value");
    params.insert(std::make_pair(key, std::shared_ptr<base::Value>(value)));
  }
  if (reader.HasMoreData())
    return GetBadArgsError(method_call,
                           "Too many parameters to StartRegisterDevice");

  LOG(INFO) << "Received call to Manager.StartRegisterDevice()";

  buffet::ErrorPtr error;
  std::string id = device_info_.StartRegistration(params, &error);
  if (id.empty())
    return GetDBusError(method_call, error.get());

  // Send back our response.
  scoped_ptr<dbus::Response> response(
      dbus::Response::FromMethodCall(method_call));
  dbus::MessageWriter writer(response.get());
  writer.AppendString(id);
  return response.Pass();
}

scoped_ptr<dbus::Response> Manager::HandleFinishRegisterDevice(
  dbus::MethodCall* method_call) {
  // Read the parameters to the method.
  dbus::MessageReader reader(method_call);
  if (!reader.HasMoreData()) {
    return GetBadArgsError(method_call,
                           "No parameters to FinishRegisterDevice");
  }
  std::string user_auth_code;
  if (!reader.PopString(&user_auth_code)) {
    return GetBadArgsError(method_call, "Failed to read UserAuthCode");
  }
  if (reader.HasMoreData()) {
    return GetBadArgsError(method_call,
                           "Too many parameters to FinishRegisterDevice");
  }

  LOG(INFO) << "Received call to Manager.FinishRegisterDevice()";
  buffet::ErrorPtr error;
  if (!device_info_.FinishRegistration(user_auth_code, &error))
    return GetDBusError(method_call, error.get());

  std::string device_id = device_info_.GetDeviceId(&error);
  if (device_id.empty())
    return GetDBusError(method_call, error.get());

  // Send back our response.
  scoped_ptr<dbus::Response> response(
    dbus::Response::FromMethodCall(method_call));
  dbus::MessageWriter writer(response.get());
  writer.AppendString(device_id);
  return response.Pass();
}

scoped_ptr<dbus::Response> Manager::HandleUpdateState(
    dbus::MethodCall *method_call) {
  // Read the parameters to the method.
  dbus::MessageReader reader(method_call);
  if (!reader.HasMoreData()) {
    return GetBadArgsError(method_call, "No parameters to UpdateState");
  }
  std::string json_state_fragment;
  if (!reader.PopString(&json_state_fragment)) {
    return GetBadArgsError(method_call, "Failed to read json_state_fragment");
  }
  if (reader.HasMoreData()) {
    return GetBadArgsError(method_call, "Too many parameters to UpdateState");
  }

  LOG(INFO) << "Received call to Manager.UpdateState()";
  // TODO(wiley): Merge json state blobs intelligently.
  properties_->state_.SetValue(json_state_fragment);

  // Send back our response.
  return dbus::Response::FromMethodCall(method_call);
}

scoped_ptr<dbus::Response> Manager::HandleTestMethod(
    dbus::MethodCall* method_call) {
  LOG(INFO) << "Received call to test method.";
  return scoped_ptr<dbus::Response>();
}

}  // namespace buffet
