// 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 "shill/dbus_adaptor.h"

#include <map>
#include <string>
#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <dbus-c++/dbus.h>

#include "shill/accessor_interface.h"
#include "shill/error.h"
#include "shill/key_value_store.h"
#include "shill/logging.h"
#include "shill/property_store.h"

using base::Bind;
using base::Owned;
using std::map;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDBus;
static string ObjectID(DBusAdaptor *d) {
  if (d == nullptr)
    return "(dbus_adaptor)";
  return d->path();
}
}

// public static
const char DBusAdaptor::kNullPath[] = "/";

DBusAdaptor::DBusAdaptor(DBus::Connection* conn, const string &object_path)
    : DBus::ObjectAdaptor(*conn, object_path) {
  SLOG(this, 2) << "DBusAdaptor: " << object_path;
}

DBusAdaptor::~DBusAdaptor() {}

// static
bool DBusAdaptor::SetProperty(PropertyStore *store,
                              const string &name,
                              const ::DBus::Variant &value,
                              ::DBus::Error *error) {
  Error e;
  bool ret;

  if (DBusAdaptor::IsBool(value.signature())) {
    ret = store->SetBoolProperty(name, value.reader().get_bool(), &e);
  } else if (DBusAdaptor::IsByte(value.signature())) {
    ret = store->SetUint8Property(name, value.reader().get_byte(), &e);
  } else if (DBusAdaptor::IsInt16(value.signature())) {
    ret = store->SetInt16Property(name, value.reader().get_int16(), &e);
  } else if (DBusAdaptor::IsInt32(value.signature())) {
    ret = store->SetInt32Property(name, value.reader().get_int32(), &e);
  } else if (DBusAdaptor::IsPath(value.signature())) {
    ret = store->SetStringProperty(name, value.reader().get_path(), &e);
  } else if (DBusAdaptor::IsString(value.signature())) {
    ret = store->SetStringProperty(name, value.reader().get_string(), &e);
  } else if (DBusAdaptor::IsStringmap(value.signature())) {
    ret = store->SetStringmapProperty(name,
                                      value.operator map<string, string>(),
                                      &e);
  } else if (DBusAdaptor::IsStringmaps(value.signature())) {
    SLOG(nullptr, 1) << " can't yet handle setting type " << value.signature();
    ret = false;
    e.Populate(Error::kInternalError);
  } else if (DBusAdaptor::IsStrings(value.signature())) {
    ret = store->SetStringsProperty(name, value.operator vector<string>(), &e);
  } else if (DBusAdaptor::IsUint16(value.signature())) {
    ret = store->SetUint16Property(name, value.reader().get_uint16(), &e);
  } else if (DBusAdaptor::IsUint16s(value.signature())) {
    ret =
        store->SetUint16sProperty(name, value.operator vector<uint16_t>(), &e);
  } else if (DBusAdaptor::IsUint32(value.signature())) {
    ret = store->SetUint32Property(name, value.reader().get_uint32(), &e);
  } else if (DBusAdaptor::IsUint64(value.signature())) {
    ret = store->SetUint64Property(name, value.reader().get_uint64(), &e);
  } else if (DBusAdaptor::IsKeyValueStore(value.signature())) {
    KeyValueStore key_value_store;
    auto dict = value.operator map<string, DBus::Variant>();
    DBusAdaptor::ArgsToKeyValueStore(dict, &key_value_store, &e);
    if (e.IsSuccess()) {
      ret = store->SetKeyValueStoreProperty(name, key_value_store, &e);
    } else {
      ret = false;
    }
  } else {
    NOTREACHED() << " unknown type: " << value.signature();
    ret = false;
    e.Populate(Error::kInternalError);
  }

  if (error != nullptr) {
    e.ToDBusError(error);
  }

  return ret;
}

// static
bool DBusAdaptor::GetProperties(const PropertyStore &store,
                                map<string, ::DBus::Variant> *out,
                                ::DBus::Error */*error*/) {
  {
    ReadablePropertyConstIterator<bool> it = store.GetBoolPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = BoolToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<int16_t> it = store.GetInt16PropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = Int16ToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<int32_t> it = store.GetInt32PropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = Int32ToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<KeyValueStore> it =
        store.GetKeyValueStorePropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = KeyValueStoreToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<RpcIdentifiers> it =
        store.GetRpcIdentifiersPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      vector < ::DBus::Path> rpc_identifiers_as_paths;
      for (const auto &path : it.value()) {
        rpc_identifiers_as_paths.push_back(path);
      }
      (*out)[it.Key()] = PathsToVariant(rpc_identifiers_as_paths);
    }
  }
  {
    ReadablePropertyConstIterator<string> it = store.GetStringPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = StringToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<Stringmap> it =
        store.GetStringmapPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()]= StringmapToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<Stringmaps> it =
        store.GetStringmapsPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()]= StringmapsToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<Strings> it =
        store.GetStringsPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = StringsToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<uint8_t> it = store.GetUint8PropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = ByteToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<uint16_t> it =
        store.GetUint16PropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = Uint16ToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<Uint16s> it =
        store.GetUint16sPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = Uint16sToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<uint32_t> it =
        store.GetUint32PropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = Uint32ToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<uint64_t> it =
        store.GetUint64PropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = Uint64ToVariant(it.value());
    }
  }
  {
    ReadablePropertyConstIterator<RpcIdentifier> it =
        store.GetRpcIdentifierPropertiesIter();
    for ( ; !it.AtEnd(); it.Advance()) {
      (*out)[it.Key()] = PathToVariant(it.value());
    }
  }
  return true;
}

// static
bool DBusAdaptor::ClearProperty(PropertyStore *store,
                                const string &name,
                                ::DBus::Error *error) {
  Error e;
  store->ClearProperty(name, &e);

  if (error != nullptr) {
    e.ToDBusError(error);
  }

  return e.IsSuccess();
}

// static
void DBusAdaptor::ArgsToKeyValueStore(
    const map<string, ::DBus::Variant> &args,
    KeyValueStore *out,
    Error *error) {  // TODO(quiche): Should be ::DBus::Error?
  for (const auto &key_value_pair : args) {
    string key = key_value_pair.first;
    DBus::type<string> string_type;
    DBus::type<bool> bool_type;
    DBus::type<int32_t> int32_type;

    if (key_value_pair.second.signature() == bool_type.sig()) {
      SLOG(nullptr, 5) << "Got bool property " << key;
      out->SetBool(key, key_value_pair.second.reader().get_bool());
    } else if (key_value_pair.second.signature() == int32_type.sig()) {
      SLOG(nullptr, 5) << "Got int32_t property " << key;
      out->SetInt(key, key_value_pair.second.reader().get_int32());
    } else if (key_value_pair.second.signature() == string_type.sig()) {
      SLOG(nullptr, 5) << "Got string property " << key;
      out->SetString(key, key_value_pair.second.reader().get_string());
    } else if (DBusAdaptor::IsKeyValueStore(
                   key_value_pair.second.signature())) {
      // Unwrap a recursive KeyValueStore object.
      KeyValueStore store;
      Error convert_error;
      DBusAdaptor::ArgsToKeyValueStore(
          key_value_pair.second.operator map<string, ::DBus::Variant>(),
          &store,
          &convert_error);
      if (convert_error.IsSuccess()) {
          out->SetKeyValueStore(key, store);
      } else {
          Error::PopulateAndLog(FROM_HERE, error, convert_error.type(),
                                convert_error.message() + " in sub-key " + key);
          return;  // Skip remaining args after error.
      }
    } else if (DBusAdaptor::IsStrings(key_value_pair.second.signature())) {
      SLOG(nullptr, 5) << "Got strings property " << key;
      out->SetStrings(key, key_value_pair.second.operator vector<string>());
    } else if (DBusAdaptor::IsStringmap(key_value_pair.second.signature())) {
      SLOG(nullptr, 5) << "Got stringmap property " << key;
      out->SetStringmap(
          key, key_value_pair.second.operator map<string, string>());
    } else {
      Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
                            "unsupported type for property " + key);
      return;  // Skip remaining args after error.
    }
  }
}

// static
string DBusAdaptor::SanitizePathElement(const string &object_path) {
  string sanitized_path(object_path);
  size_t length = sanitized_path.length();

  for (size_t i = 0; i < length; ++i) {
    char c = sanitized_path[i];
    // The D-Bus specification
    // (http://dbus.freedesktop.org/doc/dbus-specification.html) states:
    // Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
    if (!(c >= 'A' && c <= 'Z') &&
        !(c >= 'a' && c <= 'z') &&
        !(c >= '0' && c <= '9') &&
        c != '_') {
      sanitized_path[i] = '_';
    }
  }

  return sanitized_path;
}

// static
::DBus::Variant DBusAdaptor::BoolToVariant(bool value) {
  ::DBus::Variant v;
  v.writer().append_bool(value);
  return v;
}

// static
::DBus::Variant DBusAdaptor::ByteArraysToVariant(const ByteArrays &value) {
  ::DBus::MessageIter writer;
  ::DBus::Variant v;


  // We have to use a local because the operator<< needs a reference
  // to work on (the lhs) but writer() returns by-value. C++ prohibits
  // initializing non-const references from a temporary.
  // So:
  //    v.writer() << value;
  // would NOT automagically promote the returned value of v.writer() to
  // a non-const reference (if you think about it, that's almost always not what
  // you'd want. see: http://gcc.gnu.org/ml/gcc-help/2006-04/msg00075.html).
  //
  // One could consider changing writer() to return a reference, but then it
  // changes writer() semantics as it can not be a const reference. writer()
  // currently doesn't modify the original object on which it's called.
  writer = v.writer();
  writer << value;
  return v;
}

// static
::DBus::Variant DBusAdaptor::ByteToVariant(uint8_t value) {
  ::DBus::Variant v;
  v.writer().append_byte(value);
  return v;
}

// static
::DBus::Variant DBusAdaptor::Int16ToVariant(int16_t value) {
  ::DBus::Variant v;
  v.writer().append_int16(value);
  return v;
}

// static
::DBus::Variant DBusAdaptor::Int32ToVariant(int32_t value) {
  ::DBus::Variant v;
  v.writer().append_int32(value);
  return v;
}

// static
::DBus::Variant DBusAdaptor::PathToVariant(const ::DBus::Path &value) {
  ::DBus::Variant v;
  v.writer().append_path(value.c_str());
  return v;
}

// static
::DBus::Variant DBusAdaptor::PathsToVariant(const vector<::DBus::Path> &value) {
  ::DBus::MessageIter writer;
  ::DBus::Variant v;

  // See note above on why we need to use a local.
  writer = v.writer();
  writer << value;
  return v;
}

// static
::DBus::Variant DBusAdaptor::StringToVariant(const string &value) {
  ::DBus::Variant v;
  v.writer().append_string(value.c_str());
  return v;
}

// static
::DBus::Variant DBusAdaptor::StringmapToVariant(const Stringmap &value) {
  ::DBus::Variant v;
  ::DBus::MessageIter writer = v.writer();
  writer << value;
  return v;
}

// static
::DBus::Variant DBusAdaptor::StringmapsToVariant(const Stringmaps &value) {
  ::DBus::Variant v;
  ::DBus::MessageIter writer = v.writer();
  writer << value;
  return v;
}

// static
::DBus::Variant DBusAdaptor::StringsToVariant(const Strings &value) {
  ::DBus::Variant v;
  ::DBus::MessageIter writer = v.writer();
  writer << value;
  return v;
}

// static
::DBus::Variant DBusAdaptor::KeyValueStoreToVariant(
    const KeyValueStore &value) {
  DBusPropertiesMap props;
  DBusProperties::ConvertKeyValueStoreToMap(value, &props);
  ::DBus::Variant v;
  ::DBus::MessageIter writer = v.writer();
  writer << props;
  return v;
}

// static
::DBus::Variant DBusAdaptor::Uint16ToVariant(uint16_t value) {
  ::DBus::Variant v;
  v.writer().append_uint16(value);
  return v;
}

// static
::DBus::Variant DBusAdaptor::Uint16sToVariant(const Uint16s &value) {
  ::DBus::Variant v;
  ::DBus::MessageIter writer = v.writer();
  writer << value;
  return v;
}

// static
::DBus::Variant DBusAdaptor::Uint32ToVariant(uint32_t value) {
  ::DBus::Variant v;
  v.writer().append_uint32(value);
  return v;
}

// static
::DBus::Variant DBusAdaptor::Uint64ToVariant(uint64_t value) {
  ::DBus::Variant v;
  v.writer().append_uint64(value);
  return v;
}

// static
bool DBusAdaptor::IsBool(::DBus::Signature signature) {
  return signature == ::DBus::type<bool>::sig();
}

// static
bool DBusAdaptor::IsByte(::DBus::Signature signature) {
  return signature == ::DBus::type<uint8_t>::sig();
}

// static
bool DBusAdaptor::IsByteArrays(::DBus::Signature signature) {
  return signature == ::DBus::type<ByteArrays>::sig();
}

// static
bool DBusAdaptor::IsInt16(::DBus::Signature signature) {
  return signature == ::DBus::type<int16_t>::sig();
}

// static
bool DBusAdaptor::IsInt32(::DBus::Signature signature) {
  return signature == ::DBus::type<int32_t>::sig();
}

// static
bool DBusAdaptor::IsPath(::DBus::Signature signature) {
  return signature == ::DBus::type<::DBus::Path>::sig();
}

// static
bool DBusAdaptor::IsPaths(::DBus::Signature signature) {
  return signature == ::DBus::type<vector<::DBus::Path>>::sig();
}

// static
bool DBusAdaptor::IsString(::DBus::Signature signature) {
  return signature == ::DBus::type<string>::sig();
}

// static
bool DBusAdaptor::IsStringmap(::DBus::Signature signature) {
  return signature == ::DBus::type<Stringmap>::sig();
}

// static
bool DBusAdaptor::IsStringmaps(::DBus::Signature signature) {
  return signature == ::DBus::type<Stringmaps>::sig();
}

// static
bool DBusAdaptor::IsStrings(::DBus::Signature signature) {
  return signature == ::DBus::type<Strings>::sig();
}

// static
bool DBusAdaptor::IsUint16(::DBus::Signature signature) {
  return signature == ::DBus::type<uint16_t>::sig();
}

// static
bool DBusAdaptor::IsUint16s(::DBus::Signature signature) {
  return signature == ::DBus::type<Uint16s>::sig();
}

// static
bool DBusAdaptor::IsUint32(::DBus::Signature signature) {
  return signature == ::DBus::type<uint32_t>::sig();
}

// static
bool DBusAdaptor::IsUint64(::DBus::Signature signature) {
  return signature == ::DBus::type<uint64_t>::sig();
}

// static
bool DBusAdaptor::IsKeyValueStore(::DBus::Signature signature) {
  return signature == ::DBus::type<map<string, ::DBus::Variant>>::sig();
}

void DBusAdaptor::DeferReply(const DBus::Tag *tag) {
  return_later(tag);
}

void DBusAdaptor::ReplyNow(const DBus::Tag *tag) {
  Continuation *cont = find_continuation(tag);
  CHECK(cont) << "Failed to find continuation.";
  return_now(cont);
}

template <typename T>
void DBusAdaptor::TypedReplyNow(const DBus::Tag *tag, const T &value) {
  Continuation *cont = find_continuation(tag);
  CHECK(cont) << "Failed to find continuation.";
  cont->writer() << value;
  return_now(cont);
}

void DBusAdaptor::ReplyNowWithError(const DBus::Tag *tag,
                                    const DBus::Error &error) {
  Continuation *cont = find_continuation(tag);
  CHECK(cont) << "Failed to find continuation.";
  SLOG(this, 1) << "Returning error: (" << error.name() << ": "
                << error.message() << ")";
  return_error(cont, error);
}

ResultCallback DBusAdaptor::GetMethodReplyCallback(
    const DBus::Tag *tag) {
  return Bind(&DBusAdaptor::MethodReplyCallback, AsWeakPtr(), Owned(tag));
}

ResultStringCallback DBusAdaptor::GetStringMethodReplyCallback(
    const DBus::Tag *tag) {
  return Bind(&DBusAdaptor::StringMethodReplyCallback, AsWeakPtr(), Owned(tag));
}

ResultBoolCallback DBusAdaptor::GetBoolMethodReplyCallback(
    const DBus::Tag *tag) {
  return Bind(&DBusAdaptor::BoolMethodReplyCallback, AsWeakPtr(), Owned(tag));
}

template<typename T>
void DBusAdaptor::TypedMethodReplyCallback(const DBus::Tag *tag,
                                           const Error &error,
                                           const T &returned) {
  if (error.IsFailure()) {
    DBus::Error dberror;
    error.ToDBusError(&dberror);
    ReplyNowWithError(tag, dberror);
  } else {
    TypedReplyNow(tag, returned);
  }
}

void DBusAdaptor::ReturnResultOrDefer(const DBus::Tag *tag,
                                      const Error &error,
                                      DBus::Error *dberror) {
  if (error.IsOngoing()) {
    DeferReply(tag);
  } else if (error.IsFailure()) {
    error.ToDBusError(dberror);
  }
}

void DBusAdaptor::MethodReplyCallback(const DBus::Tag *tag,
                                      const Error &error) {
  if (error.IsFailure()) {
    DBus::Error dberror;
    error.ToDBusError(&dberror);
    ReplyNowWithError(tag, dberror);
  } else {
    ReplyNow(tag);
  }
}

void DBusAdaptor::StringMethodReplyCallback(const DBus::Tag *tag,
                                            const Error &error,
                                            const string &returned) {
  TypedMethodReplyCallback(tag, error, returned);
}

void DBusAdaptor::BoolMethodReplyCallback(const DBus::Tag *tag,
                                          const Error &error,
                                          bool returned) {
  TypedMethodReplyCallback(tag, error, returned);
}

}  // namespace shill
