/*
 * Copyright (C) 2012 Canonical, Ltd.
 *
 * Authors:
 *  Renato Araujo Oliveira Filho <renato@canonical.com>
 *  Ricardo Mendoza <ricmm@canonical.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "account-info.h"

struct _AccountInfoPrivate {
    GHashTable *fields;
};

AccountInfo*
account_info_new (void)
{
    AccountInfo *info = g_new0 (AccountInfo, 1);
    info->priv = g_new0 (AccountInfoPrivate, 1);
    info->priv->fields = g_hash_table_new_full (NULL, NULL,
                                                NULL,
                                                (GDestroyNotify) g_variant_unref);
    return info;
}

void
account_info_destroy (AccountInfo *self)
{
    g_debug ("DESTROY: %p\n", self);
    g_hash_table_unref (self->priv->fields);
    g_free (self->priv);
    g_free (self);
}

AccountInfo*
account_info_copy (AccountInfo *self)
{
    GHashTableIter iter;
    gpointer key;
    gpointer value;

    AccountInfo *other = account_info_new ();

    g_hash_table_iter_init (&iter, self->priv->fields);
    while (g_hash_table_iter_next (&iter, &key, &value)) {
        g_hash_table_insert (other->priv->fields, key, g_variant_ref (value));
    }

    return other;
}

gint
account_info_compare (AccountInfo *self,
                      AccountInfo *other)
{
    GHashTableIter iter;
    gpointer key;
    gpointer value;

    if (g_hash_table_size (self->priv->fields) != g_hash_table_size (other->priv->fields)) {
        return -1;
    }

    g_hash_table_iter_init (&iter, self->priv->fields);
    while (g_hash_table_iter_next (&iter, &key, &value)) {
        gpointer other_value = g_hash_table_lookup (other->priv->fields, key);
        if (other_value == NULL) {
            return -1;
        }

        gint r = g_variant_compare (value, other_value);
        if (r != 0) {
            return r;
        }
    }
    return 0;
}

gint
account_info_compare_field (AccountInfo *self,
                            AccountInfo *other,
                            AccountInfoField field)
{
    gpointer *local = g_hash_table_lookup (self->priv->fields, GINT_TO_POINTER (field));
    gpointer *remote = g_hash_table_lookup (other->priv->fields, GINT_TO_POINTER (field));
  
    return g_variant_equal (local, remote);
}

GVariant*
account_info_get_field (AccountInfo *self,
                        AccountInfoField field)
{
    AccountInfoPrivate *priv = self->priv;
    if (!priv->fields) {
        return NULL;
    }

    gpointer value = g_hash_table_lookup (self->priv->fields, GINT_TO_POINTER (field));
    g_debug ("GET FIELD: %d %p\n", field, value);
    return (GVariant*) value;
}

void
account_info_set_field (AccountInfo *self,
                        AccountInfoField field,
                        GVariant *value)
{
    AccountInfoPrivate *priv = self->priv;
    if (!priv->fields) {
        return;
    }

    GVariant *ref_value = g_variant_ref (value);
    g_hash_table_insert (priv->fields, GINT_TO_POINTER (field), (gpointer) ref_value);
}
