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

#include <dbus/dbus.h>

#include "shill/logging.h"

using std::map;
using std::string;
using std::vector;

namespace shill {

namespace {

template <typename ValueType>
bool GetValue(const DBusPropertiesMap &properties,
              const string &key,
              ValueType *value) {
  CHECK(value);

  DBusPropertiesMap::const_iterator it = properties.find(key);
  if (it == properties.end()) {
    SLOG(DBus, 2) << "Key '" << key << "' not found.";
    return false;
  }

  string actual_type = it->second.signature();
  string expected_type = DBus::type<ValueType>::sig();
  if (actual_type != expected_type) {
    SLOG(DBus, 2) << "Key '" << key << "' type mismatch (expected '"
                  << expected_type << "', actual '" << actual_type << "').";
    return false;
  }

  *value = it->second.operator ValueType();
  return true;
}

}  // namespace

// static
bool DBusProperties::GetBool(const DBusPropertiesMap &properties,
                             const string &key,
                             bool *value) {
  return GetValue<bool>(properties, key, value);
}

// static
bool DBusProperties::GetDBusPropertiesMap(const DBusPropertiesMap &properties,
                                          const string &key,
                                          DBusPropertiesMap *value) {
  return GetValue<DBusPropertiesMap>(properties, key, value);
}

// static
bool DBusProperties::GetDouble(const DBusPropertiesMap &properties,
                               const string &key,
                               double *value) {
  return GetValue<double>(properties, key, value);
}

// static
bool DBusProperties::GetInt16(const DBusPropertiesMap &properties,
                              const string &key,
                              int16 *value) {
  return GetValue<int16>(properties, key, value);
}

// static
bool DBusProperties::GetInt32(const DBusPropertiesMap &properties,
                              const string &key,
                              int32 *value) {
  return GetValue<int32>(properties, key, value);
}

// static
bool DBusProperties::GetInt64(const DBusPropertiesMap &properties,
                              const string &key,
                              int64 *value) {
  return GetValue<int64>(properties, key, value);
}

// static
bool DBusProperties::GetObjectPath(const DBusPropertiesMap &properties,
                                   const string &key,
                                   DBus::Path *value) {
  return GetValue<DBus::Path>(properties, key, value);
}

// static
bool DBusProperties::GetString(const DBusPropertiesMap &properties,
                               const string &key,
                               string *value) {
  return GetValue<string>(properties, key, value);
}

// static
bool DBusProperties::GetStrings(const DBusPropertiesMap &properties,
                                const string &key,
                                vector<string> *value) {
  return GetValue<vector<string>>(properties, key, value);
}

// static
bool DBusProperties::GetUint8(const DBusPropertiesMap &properties,
                               const string &key,
                               uint8 *value) {
  return GetValue<uint8>(properties, key, value);
}

// static
bool DBusProperties::GetUint16(const DBusPropertiesMap &properties,
                               const string &key,
                               uint16 *value) {
  return GetValue<uint16>(properties, key, value);
}

// static
bool DBusProperties::GetUint32(const DBusPropertiesMap &properties,
                               const string &key,
                               uint32 *value) {
  return GetValue<uint32>(properties, key, value);
}

// static
bool DBusProperties::GetUint64(const DBusPropertiesMap &properties,
                               const string &key,
                               uint64 *value) {
  return GetValue<uint64>(properties, key, value);
}

// static
bool DBusProperties::GetRpcIdentifiers(const DBusPropertiesMap &properties,
                                       const string &key,
                                       RpcIdentifiers *value) {
  vector<DBus::Path> paths;
  if (GetValue<vector<DBus::Path>>(properties, key, &paths)) {
    ConvertPathsToRpcIdentifiers(paths, value);
    return true;
  }
  return false;
}

// static
void DBusProperties::ConvertPathsToRpcIdentifiers(
    const vector<DBus::Path> &dbus_paths, RpcIdentifiers *rpc_identifiers) {
  CHECK(rpc_identifiers);
  rpc_identifiers->assign(dbus_paths.begin(), dbus_paths.end());
}

// static
void DBusProperties::ConvertKeyValueStoreToMap(
    const KeyValueStore &store, DBusPropertiesMap *properties) {
  CHECK(properties);
  properties->clear();
  for (const auto &key_value_pair : store.string_properties()) {
    (*properties)[key_value_pair.first].writer()
        .append_string(key_value_pair.second.c_str());
  }
  for (const auto &key_value_pair : store.strings_properties()) {
    DBus::MessageIter writer = (*properties)[key_value_pair.first].writer();
    writer << key_value_pair.second;
  }
  for (const auto &key_value_pair : store.bool_properties()) {
    (*properties)[key_value_pair.first].writer()
        .append_bool(key_value_pair.second);
  }
  for (const auto &key_value_pair : store.int_properties()) {
    (*properties)[key_value_pair.first].writer()
        .append_int32(key_value_pair.second);
  }
  for (const auto &key_value_pair : store.uint_properties()) {
    (*properties)[key_value_pair.first].writer()
        .append_uint32(key_value_pair.second);
  }
}

// static
string DBusProperties::KeysToString(const DBusPropertiesMap &properties) {
  string keys;
  for (const auto &key_value_pair : properties) {
    keys.append(" ");
    keys.append(key_value_pair.first);
  }
  return keys;
}

}  // namespace shill
