// Copyright (c) 2010 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 "update_engine/flimflam_proxy.h"

#include <string>

#include <base/string_util.h>
#include <dbus/dbus-glib.h>
#include <glib.h>

#include "update_engine/utils.h"

using std::string;

namespace chromeos_update_engine {

namespace {

// Gets the DbusGProxy for FlimFlam. Must be free'd with ProxyUnref()
bool GetFlimFlamProxy(DbusGlibInterface* dbus_iface,
                      const char* path,
                      const char* interface,
                      DBusGProxy** out_proxy) {
  DBusGConnection* bus;
  DBusGProxy* proxy;
  GError* error = NULL;

  bus = dbus_iface->BusGet(DBUS_BUS_SYSTEM, &error);
  if (!bus) {
    LOG(ERROR) << "Failed to get system bus";
    return false;
  }
  proxy = dbus_iface->ProxyNewForNameOwner(bus,
                                           kFlimFlamDbusService,
                                           path,
                                           interface,
                                           &error);
  if (!proxy) {
    LOG(ERROR) << "Error getting FlimFlam proxy: "
               << utils::GetGErrorMessage(error);
    return false;
  }
  *out_proxy = proxy;
  return true;
}

// On success, caller owns the GHashTable at out_hash_table.
// Returns true on success.
bool GetProperties(DbusGlibInterface* dbus_iface,
                   const char* path,
                   const char* interface,
                   GHashTable** out_hash_table) {
  DBusGProxy* proxy;
  GError* error = NULL;

  TEST_AND_RETURN_FALSE(GetFlimFlamProxy(dbus_iface,
                                         path,
                                         interface,
                                         &proxy));

  gboolean rc = dbus_iface->ProxyCall(proxy,
                                      "GetProperties",
                                      &error,
                                      G_TYPE_INVALID,
                                      dbus_g_type_get_map("GHashTable",
                                                          G_TYPE_STRING,
                                                          G_TYPE_VALUE),
                                      out_hash_table,
                                      G_TYPE_INVALID);
  dbus_iface->ProxyUnref(proxy);
  if (rc == FALSE) {
    LOG(ERROR) << "dbus_g_proxy_call failed";
    return false;
  }

  return true;
}

// Returns (via out_path) the default network path, or empty string if
// there's no network up.
// Returns true on success.
bool GetDefaultServicePath(DbusGlibInterface* dbus_iface, string* out_path) {
  GHashTable* hash_table = NULL;

  TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
                                      kFlimFlamDbusManagerPath,
                                      kFlimFlamDbusManagerInterface,
                                      &hash_table));

  GValue* value = reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table,
                                                                "Services"));
  GArray* array = NULL;
  bool success = false;
  if (value &&
      (array = reinterpret_cast<GArray*>(g_value_get_boxed(value))) &&
      (array->len > 0)) {
    *out_path = g_array_index(array, const char*, 0);
    success = true;
  }
  g_hash_table_unref(hash_table);
  return success;
}

NetworkConnectionType ParseConnectionType(const char* type_str) {
  if (!strcmp(type_str, kFlimFlamNetTypeEthernet)) {
    return kNetEthernet;
  } else if (!strcmp(type_str, kFlimFlamNetTypeWifi)) {
    return kNetWifi;
  } else if (!strcmp(type_str, kFlimFlamNetTypeWimax)) {
    return kNetWimax;
  } else if (!strcmp(type_str, kFlimFlamNetTypeBluetooth)) {
    return kNetBluetooth;
  } else if (!strcmp(type_str, kFlimFlamNetTypeCellular)) {
    return kNetCellular;
  }
  return kNetUnknown;
}

bool GetServicePathType(DbusGlibInterface* dbus_iface,
                        const string& path,
                        NetworkConnectionType* out_type) {
  GHashTable* hash_table = NULL;

  TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
                                      path.c_str(),
                                      kFlimFlamDbusServiceInterface,
                                      &hash_table));

  GValue* value = (GValue*)g_hash_table_lookup(hash_table, "Type");
  const char* type_str = NULL;
  bool success = false;
  if (value != NULL && (type_str = g_value_get_string(value)) != NULL) {
    *out_type = ParseConnectionType(type_str);
    success = true;
  }
  g_hash_table_unref(hash_table);
  return success;
}

}  // namespace {}

const char* FlimFlamProxy::StringForConnectionType(NetworkConnectionType type) {
  static const char* const kValues[] = {kFlimFlamNetTypeEthernet,
                                        kFlimFlamNetTypeWifi,
                                        kFlimFlamNetTypeWimax,
                                        kFlimFlamNetTypeBluetooth,
                                        kFlimFlamNetTypeCellular};
  if (type < 0 || type >= static_cast<int>(arraysize(kValues))) {
    return "Unknown";
  }
  return kValues[type];
}

bool FlimFlamProxy::GetConnectionType(DbusGlibInterface* dbus_iface,
                                      NetworkConnectionType* out_type) {
  string default_service_path;
  TEST_AND_RETURN_FALSE(GetDefaultServicePath(dbus_iface,
                                              &default_service_path));
  TEST_AND_RETURN_FALSE(GetServicePathType(dbus_iface,
                                           default_service_path,
                                           out_type));
  return true;
}

const char* kFlimFlamDbusService = "org.chromium.flimflam";
const char* kFlimFlamDbusManagerInterface = "org.chromium.flimflam.Manager";
const char* kFlimFlamDbusManagerPath = "/";
const char* kFlimFlamDbusServiceInterface = "org.chromium.flimflam.Service";

const char* kFlimFlamNetTypeEthernet = "ethernet";
const char* kFlimFlamNetTypeWifi = "wifi";
const char* kFlimFlamNetTypeWimax = "wimax";
const char* kFlimFlamNetTypeBluetooth = "bluetooth";
const char* kFlimFlamNetTypeCellular = "cellular";

}  // namespace chromeos_update_engine
