/* sml_dev_inf_prop_param.c
 *
 * Copyright (C) 2009 Michael Bell <michael.bell@opensync.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 */


#include "sml_dev_inf_prop_param.h"
#include <libsyncml/syncml.h>
#include "../sml_error_internals.h"

G_DEFINE_TYPE (SmlDevInfPropParam, sml_dev_inf_prop_param, G_TYPE_OBJECT)

enum
{
	PROP_0,
	PROP_PARAM_NAME,
	PROP_DATA_TYPE,
	PROP_DISPLAY_NAME,
	PROP_VAL_ENUMS
};

struct _SmlDevInfPropParamPrivate
{
	gchar*  param_name;
	gchar*  data_type;
	gchar*  display_name;
	GList*  val_enums;
};

static void
sml_dev_inf_prop_param_get_property (GObject    *object,
                                     guint       property_id,
                                     GValue     *value,
                                     GParamSpec *pspec)
{
	switch (property_id) {
	case PROP_PARAM_NAME:
		g_value_set_string (value, SML_DEV_INF_PROP_PARAM (object)->priv->param_name);
		break;
	case PROP_DATA_TYPE:
		g_value_set_string (value, SML_DEV_INF_PROP_PARAM (object)->priv->data_type);
		break;
	case PROP_DISPLAY_NAME:
		g_value_set_string (value, SML_DEV_INF_PROP_PARAM (object)->priv->display_name);
		break;
	case PROP_VAL_ENUMS:
		g_value_set_pointer (value, SML_DEV_INF_PROP_PARAM (object)->priv->val_enums);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
	}
}

static void
sml_dev_inf_prop_param_set_property (GObject      *object,
                                     guint         property_id,
                                     const GValue *value,
                                     GParamSpec   *pspec)
{
	switch (property_id) {
	case PROP_PARAM_NAME:
		g_free (SML_DEV_INF_PROP_PARAM (object)->priv->param_name);
		SML_DEV_INF_PROP_PARAM (object)->priv->param_name = g_strdup (g_value_get_string (value));
		break;
	case PROP_DATA_TYPE:
		g_free (SML_DEV_INF_PROP_PARAM (object)->priv->data_type);
		SML_DEV_INF_PROP_PARAM (object)->priv->data_type = g_strdup (g_value_get_string (value));
		break;
	case PROP_DISPLAY_NAME:
		g_free (SML_DEV_INF_PROP_PARAM (object)->priv->display_name);
		SML_DEV_INF_PROP_PARAM (object)->priv->display_name = g_strdup (g_value_get_string (value));
		break;
	case PROP_VAL_ENUMS:
		SML_DEV_INF_PROP_PARAM (object)->priv->val_enums = (GList *) g_value_get_pointer(value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
	}
}

static void
sml_dev_inf_prop_param_finalize (GObject *object)
{
	SmlDevInfPropParam *self = (SmlDevInfPropParam *) object;
	g_free(self->priv->param_name);
	g_free(self->priv->data_type);
	g_free(self->priv->display_name);
	while(self->priv->val_enums) {
		gchar *val_enum = self->priv->val_enums->data;
		self->priv->val_enums = g_list_remove(self->priv->val_enums, val_enum);
		g_free(val_enum);
	}
	/* all pointers must be NULL */
	self->priv->param_name = NULL;
	self->priv->data_type = NULL;
	self->priv->display_name = NULL;
	G_OBJECT_CLASS (sml_dev_inf_prop_param_parent_class)->finalize (object);
}

static void
sml_dev_inf_prop_param_class_init (SmlDevInfPropParamClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

	g_type_class_add_private (klass, sizeof (SmlDevInfPropParamPrivate));

	object_class->get_property = sml_dev_inf_prop_param_get_property;
	object_class->set_property = sml_dev_inf_prop_param_set_property;
	object_class->finalize     = sml_dev_inf_prop_param_finalize;

	/**
	 * SmlDevInfPropParam:ParamName:
	 *
	 * The  property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_PARAM_NAME,
	                                 g_param_spec_string ("ParamName",
	                                                      "",
	                                                      "",
	                                                      NULL,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfPropParam:DataType:
	 *
	 * The  property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_DATA_TYPE,
	                                 g_param_spec_string ("DataType",
	                                                      "",
	                                                      "",
	                                                      NULL,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfPropParam:DisplayName:
	 *
	 * The  property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_DISPLAY_NAME,
	                                 g_param_spec_string ("DisplayName",
	                                                      "",
	                                                      "",
	                                                      NULL,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfPropParam:ValEnums:
	 *
	 * The  property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_VAL_ENUMS,
	                                 g_param_spec_pointer ("ValEnums",
	                                                      "",
	                                                      NULL,
	                                                      G_PARAM_PRIVATE));

}

static void
sml_dev_inf_prop_param_init (SmlDevInfPropParam *self)
{
	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
	                                          SML_TYPE_DEV_INF_PROP_PARAM,
	                                          SmlDevInfPropParamPrivate);
}

/**
 * sml_dev_inf_prop_param_new:
 *
 * Creates a new instance of #SmlDevInfPropParam.
 *
 * Return value: the newly created #SmlDevInfPropParam instance
 */
SmlDevInfPropParam*
sml_dev_inf_prop_param_new (void)
{
	return g_object_new (SML_TYPE_DEV_INF_PROP_PARAM, NULL);
}

/**
 * sml_dev_inf_prop_param_get_param_name:
 * @self: A #SmlDevInfPropParam
 *
 * Gets the  property.
 *
 * Return value: 
 */
G_CONST_RETURN gchar*
sml_dev_inf_prop_param_get_param_name (SmlDevInfPropParam *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), NULL);
	return self->priv->param_name;
}

/**
 * sml_dev_inf_prop_param_set_param_name:
 * @self: A #SmlDevInfPropParam
 * @paramname:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_prop_param_set_param_name (SmlDevInfPropParam *self,
                                       const gchar* param_name,
                                       GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfPropParam object.");
	sml_return_val_error_if_fail (param_name, FALSE, error, SML_ERROR_GENERIC, "The parameter name is required.");
	sml_return_val_error_if_fail (strlen(param_name) > 0, FALSE, error, SML_ERROR_GENERIC, "The parameter name must not be the empty.");

	g_free (self->priv->param_name);

	self->priv->param_name = g_strdup (param_name);
	sml_return_val_error_if_fail (self->priv->param_name, FALSE, error, SML_ERROR_GENERIC, "Cannot copy parameter name - out of memory.");

	return TRUE;
}

/**
 * sml_dev_inf_prop_param_get_data_type:
 * @self: A #SmlDevInfPropParam
 *
 * Gets the  property.
 *
 * Return value: 
 */
G_CONST_RETURN gchar*
sml_dev_inf_prop_param_get_data_type (SmlDevInfPropParam *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), NULL);
	return self->priv->data_type;
}

/**
 * sml_dev_inf_prop_param_set_data_type:
 * @self: A #SmlDevInfPropParam
 * @datatype:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_prop_param_set_data_type (SmlDevInfPropParam *self,
                                      const gchar* data_type,
                                      GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfPropParam object.");

	g_free (self->priv->data_type);

	/* normalization */
	if (data_type && strlen(data_type) == 0)
		data_type = NULL;

	self->priv->data_type = g_strdup (data_type);
	sml_return_val_error_if_fail (!data_type || self->priv->data_type, FALSE, error, SML_ERROR_GENERIC, "Cannot copy data type - out of memory.");

	return TRUE;
}

/**
 * sml_dev_inf_prop_param_get_display_name:
 * @self: A #SmlDevInfPropParam
 *
 * Gets the  property.
 *
 * Return value: 
 */
G_CONST_RETURN gchar*
sml_dev_inf_prop_param_get_display_name (SmlDevInfPropParam *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), NULL);
	return self->priv->display_name;
}

/**
 * sml_dev_inf_prop_param_set_display_name:
 * @self: A #SmlDevInfPropParam
 * @displayname:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_prop_param_set_display_name (SmlDevInfPropParam *self,
                                         const gchar* display_name,
                                         GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfPropParam object.");

	g_free (self->priv->display_name);

	/* normalization */
	if (display_name && strlen(display_name) == 0)
		display_name = NULL;

	self->priv->display_name = g_strdup (display_name);
	sml_return_val_error_if_fail (!display_name || self->priv->display_name, FALSE, error, SML_ERROR_GENERIC, "Cannot copy display name - out of memory.");

	return TRUE;
}

/**
 * sml_dev_inf_prop_param_num_val_enums:
 * @self: A #SmlDevInfPropParam
 *
 * 
 */
gsize
sml_dev_inf_prop_param_num_val_enums (SmlDevInfPropParam *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), 0);
	return g_list_length(self->priv->val_enums);
}

/**
 * sml_dev_inf_prop_param_get_nth_val_enum:
 * @self: A #SmlDevInfPropParam
 *
 * 
 */
G_CONST_RETURN gchar*
sml_dev_inf_prop_param_get_nth_val_enum (SmlDevInfPropParam *self,
                                         gsize n)
{
	g_return_val_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), NULL);
	return (gchar *)g_list_nth_data(self->priv->val_enums, n);
}

/**
 * sml_dev_inf_prop_param_add_val_enum:
 * @self: A #SmlDevInfPropParam
 *
 * 
 */
gboolean
sml_dev_inf_prop_param_add_val_enum (SmlDevInfPropParam *self,
                                     const gchar* val_enum,
                                     GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_PROP_PARAM (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfPropParam object.");
	sml_return_val_error_if_fail (val_enum, FALSE, error, SML_ERROR_GENERIC, "The ValEnum must be filled.");
	sml_return_val_error_if_fail (strlen(val_enum), FALSE, error, SML_ERROR_GENERIC, "The ValEnum must not be the empty word.");

	self->priv->val_enums = g_list_append(self->priv->val_enums, g_strdup(val_enum));
	sml_return_val_error_if_fail (self->priv->val_enums, FALSE, error, SML_ERROR_GENERIC, "Cannot add ValEnum to ValEnum list of PropParam.");

	return TRUE;
}
