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

#include <string>

#include <base/strings/stringprintf.h>

#include "shill/logging.h"

using std::string;

namespace shill {

GLib::GLib() {}
GLib::~GLib() {}

std::string GLib::ConvertErrorToMessage(GError* error) {
  if (!error) {
    return "Unknown GLib error.";
  }
  std::string message =
      base::StringPrintf("GError(%d): %s", error->code, error->message);
  g_error_free(error);
  return message;
}

bool GLib::B64Decode(const string& input, string* output) {
  CHECK(output);
  gsize result_len = 0;
  guchar* result = g_base64_decode(input.c_str(), &result_len);
  if (!result) {
    LOG(ERROR) << "Failed in encoding.";
    return false;
  }

  if (!result_len) {
    LOG(ERROR) << "Failed in encoding.";
    Free(result);
    return false;
  }

  output->assign(reinterpret_cast<char*>(result), result_len);
  Free(result);
  return true;
}

bool GLib::B64Encode(const string& input, string* output) {
  CHECK(output);
  gchar* result = g_base64_encode(
      reinterpret_cast<const unsigned char*>(input.c_str()), input.length());
  if (!result) {
    LOG(ERROR) << "Failed in encoding.";
    return false;
  }

  output->assign(result);
  Free(result);
  return true;
}

guint GLib::ChildWatchAdd(GPid pid,
                          GChildWatchFunc function,
                          gpointer data) {
  return g_child_watch_add(pid, function, data);
}

void GLib::Free(gpointer mem) {
  g_free(mem);
}

void GLib::KeyFileFree(GKeyFile* key_file) {
  g_key_file_free(key_file);
}

gboolean GLib::KeyFileLoadFromFile(GKeyFile* key_file,
                                   const gchar* file,
                                   GKeyFileFlags flags,
                                   GError** error) {
  return g_key_file_load_from_file(key_file, file, flags, error);
}

gboolean GLib::KeyFileGetBoolean(GKeyFile* key_file,
                                 const gchar* group_name,
                                 const gchar* key,
                                 GError** error) {
  return g_key_file_get_boolean(key_file, group_name, key, error);
}

gchar** GLib::KeyFileGetGroups(GKeyFile* key_file,
                               gsize* length) {
  return g_key_file_get_groups(key_file, length);
}

gint GLib::KeyFileGetInteger(GKeyFile* key_file,
                             const gchar* group_name,
                             const gchar* key,
                             GError** error) {
  return g_key_file_get_integer(key_file, group_name, key, error);
}

gchar* GLib::KeyFileGetString(GKeyFile* key_file,
                              const gchar* group_name,
                              const gchar* key,
                              GError** error) {
  return g_key_file_get_string(key_file, group_name, key, error);
}

gchar** GLib::KeyFileGetStringList(GKeyFile* key_file,
                                   const gchar* group_name,
                                   const gchar* key,
                                   gsize* length,
                                   GError** error) {
  return g_key_file_get_string_list(key_file, group_name, key, length, error);
}

gboolean GLib::KeyFileHasGroup(GKeyFile* key_file,
                               const gchar* group_name) {
  return g_key_file_has_group(key_file, group_name);
}

gboolean GLib::KeyFileHasKey(GKeyFile* key_file,
                             const gchar* group_name,
                             const gchar* key,
                             GError** error) {
  return g_key_file_has_key(key_file, group_name, key, error);
}

GKeyFile* GLib::KeyFileNew() {
  return g_key_file_new();
}

void GLib::KeyFileRemoveGroup(GKeyFile* key_file,
                              const gchar* group_name,
                              GError** error) {
  g_key_file_remove_group(key_file, group_name, error);
}

void GLib::KeyFileRemoveKey(GKeyFile* key_file,
                            const gchar* group_name,
                            const gchar* key,
                            GError** error) {
  g_key_file_remove_key(key_file, group_name, key, error);
}

void GLib::KeyFileSetBoolean(GKeyFile* key_file,
                             const gchar* group_name,
                             const gchar* key,
                             gboolean value) {
  g_key_file_set_boolean(key_file, group_name, key, value);
}

gboolean GLib::KeyFileSetComment(GKeyFile* key_file,
                                 const gchar* group_name,
                                 const gchar* key,
                                 const gchar* comment,
                                 GError** error) {
  return g_key_file_set_comment(key_file, group_name, key, comment, error);
}

void GLib::KeyFileSetInteger(GKeyFile* key_file,
                             const gchar* group_name,
                             const gchar* key,
                             gint value) {
  g_key_file_set_integer(key_file, group_name, key, value);
}

void GLib::KeyFileSetString(GKeyFile* key_file,
                            const gchar* group_name,
                            const gchar* key,
                            const gchar* value) {
  g_key_file_set_string(key_file, group_name, key, value);
}

void GLib::KeyFileSetStringList(GKeyFile* key_file,
                                const gchar* group_name,
                                const gchar* key,
                                const gchar* const list[],
                                gsize length) {
  g_key_file_set_string_list(key_file, group_name, key, list, length);
}

gchar* GLib::KeyFileToData(GKeyFile* key_file,
                           gsize* length,
                           GError** error) {
  return g_key_file_to_data(key_file, length, error);
}

gboolean GLib::SourceRemove(guint tag) {
  return g_source_remove(tag);
}

gboolean GLib::SpawnAsync(const gchar* working_directory,
                          gchar** argv,
                          gchar** envp,
                          GSpawnFlags flags,
                          GSpawnChildSetupFunc child_setup,
                          gpointer user_data,
                          GPid* child_pid,
                          GError** error) {
  return g_spawn_async(working_directory,
                       argv,
                       envp,
                       flags,
                       child_setup,
                       user_data,
                       child_pid,
                       error);
}

void GLib::SpawnClosePID(GPid pid) {
  g_spawn_close_pid(pid);
}

gboolean GLib::SpawnSync(const gchar* working_directory,
                         gchar** argv,
                         gchar** envp,
                         GSpawnFlags flags,
                         GSpawnChildSetupFunc child_setup,
                         gpointer user_data,
                         gchar** standard_output,
                         gchar** standard_error,
                         gint* exit_status,
                         GError** error) {
  return g_spawn_sync(working_directory,
                      argv,
                      envp,
                      flags,
                      child_setup,
                      user_data,
                      standard_output,
                      standard_error,
                      exit_status,
                      error);
}

void GLib::Strfreev(gchar** str_array) {
  g_strfreev(str_array);
}

void GLib::TypeInit() {
  g_type_init();
}

}  // namespace shill
