/**
 *
 * @ingroup   SLP_PG
 * @defgroup   MESSAGE MessagingFW
@{
<h1 class="pg">Introduction</h1>
	<h2 class="pg">Purpose</h2>
The purpose of this document is to describe how applications can use the Messaging Framework APIs to send and receive SMS and MMS messages. This document gives programming guidelines to application engineers.

	<h2 class="pg">Scope</h2>
The scope of this document is limited to Messaging Framework APIs usage.

	<h2 class="pg">Abbreviations</h2>
<table>
<tr><td>API</td><td>Application Programming Interface</td></tr>
</table>
@}

@defgroup Message_Architecture 1.Archtecture
@ingroup MESSAGE
@{
<h1>Messaging Framework Architecture</h1>
The Messaging framework supports various messaging services such as SMS, MMS, Cell Broadcast, WAP Push, and Provisioning message. The Messaging framework architecture consists of a Messaging daemon and a library. The messaging library works on application process and provides various APIs to support transport, control, storage, filter and setting services for application. The messaging daemon has three components (transaction manager, transaction handler, and plug-in manager) to provide message services. The socket IPC is used to communicate (request & event) between Messaging daemon and library.
@image html messaging_image001.png

- Transaction Manager
	- Receive the IPC message (request) on socket.
	- Manage list of pairs (request ID, transaction proxy) for synchronous return.
	- Determine the transaction flow based on request/event information. (Mapping the request to one of the handlers)
	- Store the transaction information for asynchronous events (Find which transaction proxy want to receive SMS)
- Transaction Handler
	- Submit handler deals with submit requests.
	- Deliver handler deals with the incoming message from plug-ins.
	- Storage handler deals with the messages, accounts and folder requests
	- Filter handler deals with the filter requests
	- Setting handler deals with the service-specific attributes
- Plug-in Manager
	- Initialize all plug-ins after loading plug-in configuration files
	- Holding the list of plug-ins and the state of plug-ins
	- Providing the interface between handlers and plug-ins
- Transaction Handlers
	- Initialize all plug-ins after loading plug-in configuration files
	- Receiving IPC messages from messaging daemon.
	- Handling synchronous calls
		- Condition variable is used for waiting the return from msg-server)
	- Handling asynchronous calls or events
		- Proxy listener is a component of transaction proxy
		- Proxy listener is waiting for the event
		- Invoking callback function in the msg. handle list
		- i.e. calling incoming callback function of MSG APP handle, when incoming msg
	- Holding list of message handles
		- Message handle is created by msg_open_msg_handle(msgHandle)
		- Message handle holds some info such as callback func
- Message API
	- Transport & control API
	- Storage API
	- Filter API
	- Setting API
@}

@defgroup Message_Feature 2.Feature
@ingroup MESSAGE
@{
	<h2 class="pg">Messaging Framework Features</h2>
-# Message Control Features:
	-# Open/Close message handle
-# Message Transport Features:
	-# Submit request to send, forward, reply, retrieve message.
	-# Register callback functions to listen to invoked events from messaging daemon. (message status callback, incoming message callback)
-# Message Storage Features:
	-# Add / Update / Move / Delete / Count / Get message or message list.
	-# Add / Update / Delete / Get folder or folder list.
-# Message Filter Features:
	-# Add / Update / Delete filter or filter list.
-# Message Setting Features:
	-# Set / Get various message setting (i.e. whether to send read/delivery report or not)
@}

@defgroup MESSAGE_USECASES_1 Initialize/Finalization
@ingroup MESSAGE_USECASES
@{
	<h2 class="pg">Messaging Framework Functions</h2>

		<h3 class="pg">Initialization / Finalization to use Messaging Service </h3>
- int msg_open_msg_handle(msg_handle_t *handle);
@n msg_open_msg_handle() should be called before using the messaging service. This function opens a channel between the application and the messaging framework.
- int msg_close_msg_handle(msg_handle_t *handle);
@n msg_close_msg_handle() should be called after using the messaging service. This function closes a channel between the application and the messaging framework.
- int msg_reg_sent_status_callback(msg_handle_t handle, msg_sent_status_cb cb, void *user_param);
@n Application could implement a msg_sent_status_cb function and register it into message handle. If the application sends a message, this callback function will be called to report its sending status. msg_reg_set_status_callback function should be called after creation of message handle.
- int  msg_reg_sms_message_callback(msg_handle_t handle, msg_sms_incoming_cb cb, unsigned short port, void *user_param);
@n Application could implement a msg_sms_incoming_cb function and register it into message handle. It’s used to listen to the SMS incoming event invoked by messaging daemon. The incoming message information structure (MSG_MESSAGE_S) can be delivered as a parameter of the callback function.
- int msg_reg_mms_conf_message_callback(msg_handle_t handle, msg_mms_conf_msg_incoming_cb cb, const char *app_id, void *user_param);
@n Application could implement a msg_mms_conf_msg_incoming_cb function and register it into message handle. It’s used to listen to the MMS incoming event invoked by messaging daemon. The incoming message information structure (MSG_MESSAGE_S) can be delivered as a parameter of the callback function.
@code
#include <stdio.h>
#include <glib.h>
#include <msg.h>
#include <msg_transport.h>

void sentStatusCB(msg_handle_t hMsgHandle, msg_struct_t sent_status, void *user_param)
{
	// Application can handle message sent status event
}

void incomingSmsMessageCB(msg_handle_t hMsgHandle, msg_struct_t msg, void *user_param)
{
	// Application can handle SMS incoming message.
}

void incomingMmsConfMessageCB(msg_handle_t hMsgHandle, msg_struct_t msg, void *user_param)
{
	// Application can handle MMS incoming message.
}

int main(void)
{
	msg_handle_t msgHandle = NULL;

	err = msg_open_msg_handle(&msgHandle);

	if (err != MSG_SUCCESS)
	{
		printf("msg_open_msg_handle() Fail [%d]", err);
		return err;
	}

	// Register sent status handler
	err = msg_reg_sent_status_callback(msgHandle, &sentStatusCB, NULL);

	if (err != MSG_SUCCESS)
	{
		printf("msg_reg_sent_status_callback() Fail [%d]", err);
		return err;
	}

	// Register SMS incoming message handler
	err = msg_reg_sms_message_callback(msgHandle, &incomingSmsMessageCB, NULL);

	if (err != MSG_SUCCESS)
	{
		printf("msg_reg_sms_message_callback() Fail [%d]", err);
		return err;
	}

	// Register MMS incoming message handler
	err = msg_reg_mms_conf_message_callback(msgHandle, &incomingMmsConfMessageCB, NULL);

	if (err != MSG_SUCCESS)
	{
		printf("msg_reg_mms_conf_message_callback() Fail [%d]", err);
		return err;
	}

	// g_main_loop should be used to listen CB event from messaging daemon
	mainloop = g_main_loop_new(NULL, FALSE);
	g_main_loop_run(mainloop);

	msg_close_msg_handle(&msgHandle);

	return err;
}
@endcode
@}

@defgroup MESSAGE_USECASES_2 Adding a SMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Adding a SMS Message</h3>
- msg_struct_t msgInfo = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
@n msg_create_struct(MSG_STRUCT_MESSAGE_INFO) is a function to create a message object which can store the message information. You should call this function to set the message that you want to add or send.
- int msg_set_int_value(msg_struct_t msg_struct_handle, int field, int value);
@n msg_set_int_value(msgInfo, MSG_MESSAGE_TYPE_INT, ) is a function to set the message type such as SMS or MMS. The first parameter is the message object which is created by msg_create_struct(). The second parameter is the message type you want to set. It should be one of enum type ( _MSG_MESSAGE_INFO_E_). If setting is successful, the function returns MSG_SUCCESS. Otherwise it returns an error in enum type (_MSG_ERROR_E).
- int msg_set_str_value(msg_struct_t msg_struct_handle, int field, char *value, int size);
@n msg_set_str_value(msgInfo, MSG_MESSAGE_SMS_DATA_STR, , ) is a function to set the SMS body data. The first parameter is the message object which is created by msg_create_struct(). The second parameter is the SMS body data you want to set. The third parameter is the length of SMS body data. If setting is successful, the function returns MSG_SUCCESS. Otherwise it returns an error in enum type (_MSG_ERROR_E).
- int msg_list_add_item(msg_struct_t msg_struct_handle, int field, msg_struct_t *item);
@n msg_list_add_item() is a function to add the phone numbers for the message. The first parameter is the message object which is created by msg_create_struct(). The second parameter is the field of handle you want to set. You can add several phone numbers at once. The phone numbers should be added by this function. The third parameter is the msg_struct_t item of address. If setting is successful, the function returns MSG_SUCCESS. Otherwise it returns an error in enum type (_MSG_ERROR_E).
- int msg_add_message(msg_handle_t handle, const msg_struct_t msg, const msg_struct_t send_opt);
@n msg_add_message() is a function to add a composed message into the database of messaging framework. Before calling this function, the application should set the message object and the sending option structure and then pass them as parameters. If you don't want to change the current sending option, do not change the values of send_opt. If saving a message is successful, the function returns MSG_SUCCESS. Otherwise it returns an error in enum type (_MSG_ERROR_E).
- int msg_release_struct(msg_struct_t *msg_struct_handle);
@n msg_release_struct() is a function to free the memory of a message object which is create by msg_create_struct(). If freeing the memory is successful, the function returns MSG_SUCCESS. Otherwise it returns an error in enum type (_MSG_ERROR_E).
@code
#include <string.h>
#include <msg.h>
#include <msg_storage.h>
#include <msg_types.h>

void test_add_sms_message(msg_handle_t hMsgHandle)
{
	MSG_ERROR_T err = MSG_SUCCESS;

	msg_struct_t msgInfo = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
	msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);

	// Set Message Type
	err = msg_set_int_value(msgInfo, MSG_MESSAGE_TYPE_INT, MSG_TYPE_SMS);

	if (err != MSG_SUCCESS) goto free_memory;

	char msgText[1024];

	memset(msgText, 0x00, 1024);
	strncpy(msgText, "Test SMS Message", sizeof(msgText)-1);
	int dataSize = strlen(msgText);

	// Set SMS text
	err = msg_set_str_value(msgInfo, MSG_MESSAGE_SMS_DATA_STR, msgText, strlen(msgText);

	if (err != MSG_SUCCESS) goto free_memory;

	char number[MAX_ADDRESS_VAL_LEN];

	memset(number, 0x00, MAX_ADDRESS_VAL_LEN);
	strncpy(number, "+821030011234", sizeof(number)-1);

	// Set Recipient Address
	msg_struct_t tmpAddr;
	
	msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT, MSG_RECIPIENTS_TYPE_TO);
	msg_set_str_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, number, strlen(number));

	msg_list_add_item(msgInfo, MSG_MESSAGE_ADDR_LIST_HND, &tmpAddr);

	if (err != MSG_SUCCESS) goto free_memory;

	err = msg_add_message(hMsgHandle, msgInfo, sendOpt);

	if (err == MSG_SUCCESS)
		printf("Saving Message is OK!");
	else
		printf("Saving Message is failed!");

free_memory:
	msg_release_struct(&msgInfo);
	msg_release_struct(&sendOpt);
}
@endcode
@}

@defgroup MESSAGE_USECASES_3 Adding a MMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Adding a MMS Message</h3>
- int msg_set_str_value(msgInfo, MSG_MESSAGE_SUBJECT_STR, subject, strlen(subject));
@n msg_set_str_value(msgInfo, MSG_MESSAGE_SUBJECT_STR, , ) is a function to set the subject of MMS. The first parameter is the message object which is created by msg_create_struct(). The second parameter is enumeration to set subject. The third parameter is the subject you want to set. If setting is successful, the function returns MSG_SUCCESS. Otherwise it returns an error in enum type (_MSG_ERROR_E).

- msg_struct_t msg_create_struct(MSG_STRUCT_MMS);
@n msg_create_struct(MSG_STRUCT_MMS) allocates a MMS data structure and returns it's address.

- Enumeration with MSG_MMS_ROOTLAYOUT_WIDTH_ prefix in MSG_MMS_INFO_E.
@n Enumerations to set smil root layout. The parameters representing the size and background color of smil root layout should be set.

- Enumeration with MSG_MMS_REGION_ prefix(MSG_MMS_REGION_INFO_E).
@n Enumerations to set region. Smil region is needed to display text message, image, and video data (Each content has its own region). This function is called to allocate a region for each contents.

- Enumeration with MSG_MMS_PAGE_ prefix(MSG_MMS_PAGE_INFO_E).
@n Enumerations to add a smil page.

- Enumeration with MSG_MMS_MEDIA_ prefix(MSG_MMS_MEDIA_INFO).
@n Enumerations to add multimedia content to a mms message. If some content should be played with smil player, this function can be used.

- Enumeration with MSG_MMS_ATTACH_ prefix(MSG_MMS_ATTACH_INFO_E).
@n Enumerations to add a content as an attached file. With this function a content might be attached as a multipart mixed type.

- int msg_set_mms_struct(msg_struct_t msg_struct_handle, msg_struct_t mms_struct_handle);
@n It is a function to set the MMS body data. The first parameter is the message object which is created by msg_create_struct(). The second parameter is the structure which is allocated by msg_create_struct(MSG_STRUCT_MMS) and is set by the APIs for MMS.

@code
#include <string.h>
#include <msg.h>
#include <msg_storage.h>
#include <msg_types.h>

void test_add_mms_message(MSG_HANDLE_T hMsgHandle)
{
	MSG_ERROR_T err = MSG_SUCCESS;

	msg_struct_t msgInfo = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
	msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);

	// Set Message Type
	err = msg_set_int_value(msgInfo, MSG_MESSAGE_TYPE_INT, MSG_TYPE_MMS);

	if (err != MSG_SUCCESS) goto free_memory;

	// Set MMS subject
	char subject[MAX_SUBJECT_LEN];

	memset(subject, 0x00, MAX_SUBJECT_LEN);
	strncpy(subject, "hello mms", sizeof(subject)-1);

	err = msg_set_str_value(msgInfo, MSG_MESSAGE_SUBJECT_STR, subject, strlen(subject));

	if (err != MSG_SUCCESS) goto free_memory;

	// Set MMS Body data
	msg_struct_t mms_data;
	msg_struct_t region[2];
	msg_struct_t page[2];
	msg_struct_t media[5];
	msg_struct_t attachment[1];
	msg_struct_t smil_text[2];

	msg_struct_t mms_data = msg_create_struct(MSG_STRUCT_MMS);

	// set rootlayout
	msg_set_int_value(mms_data, MSG_MMS_ROOTLAYOUT_WIDTH_INT, 100);
	msg_set_int_value(mms_data, MSG_MMS_ROOTLAYOUT_HEIGHT_INT, 100);

	msg_set_bool_value(mms_data, MSG_MMS_ROOTLAYOUT_WIDTH_PERCENT_BOOL, true);
	msg_set_bool_value(mms_data, MSG_MMS_ROOTLAYOUT_HEIGHT_PERCENT_BOOL, true);

	//set region
	msg_list_add_item(mms_data, MSG_STRUCT_MMS_REGION, &region[0]);
	msg_set_str_value(region[0], MSG_MMS_REGION_ID_STR, (char *)"Image", 5);
	msg_set_int_value(region[0], MSG_MMS_REGION_LENGTH_LEFT_INT, 0);
	msg_set_int_value(region[0], MSG_MMS_REGION_LENGTH_TOP_INT, 50);
	msg_set_int_value(region[0], MSG_MMS_REGION_LENGTH_WIDTH_INT, 100);
	msg_set_int_value(region[0], MSG_MMS_REGION_LENGTH_HEIGHT_INT, 50);
	msg_set_int_value(region[0], MSG_MMS_REGION_BGCOLOR_INT, 0xffffff);

	msg_set_bool_value(region[0], MSG_MMS_REGION_LENGTH_LEFT_PERCENT_BOOL, true);
	msg_set_bool_value(region[0], MSG_MMS_REGION_LENGTH_TOP_PERCENT_BOOL, true);
	msg_set_bool_value(region[0], MSG_MMS_REGION_LENGTH_WIDTH_PERCENT_BOOL, true);
	msg_set_bool_value(region[0], MSG_MMS_REGION_LENGTH_HEIGHT_PERCENT_BOOL, true);

	msg_list_add_item(mms_data, MSG_STRUCT_MMS_REGION, &region[1]);
	msg_set_str_value(region[1], MSG_MMS_REGION_ID_STR, (char *)"Text", 5);
	msg_set_int_value(region[1], MSG_MMS_REGION_LENGTH_LEFT_INT, 0);
	msg_set_int_value(region[1], MSG_MMS_REGION_LENGTH_TOP_INT, 0);
	msg_set_int_value(region[1], MSG_MMS_REGION_LENGTH_WIDTH_INT, 100);
	msg_set_int_value(region[1], MSG_MMS_REGION_LENGTH_HEIGHT_INT, 50);
	//msg_set_int_value(region[1], MSG_MMS_REGION_BGCOLOR_INT, 0xffffff);

	msg_set_bool_value(region[1], MSG_MMS_REGION_LENGTH_LEFT_PERCENT_BOOL, true);
	msg_set_bool_value(region[1], MSG_MMS_REGION_LENGTH_TOP_PERCENT_BOOL, true);
	msg_set_bool_value(region[1], MSG_MMS_REGION_LENGTH_WIDTH_PERCENT_BOOL, true);
	msg_set_bool_value(region[1], MSG_MMS_REGION_LENGTH_HEIGHT_PERCENT_BOOL, true);

	//add page
	msg_list_add_item(mms_data, MSG_STRUCT_MMS_PAGE, &page[0]);
	msg_set_int_value(page[0], MSG_MMS_PAGE_PAGE_DURATION_INT, 5440);

	msg_mms_add_item(page[0], MSG_STRUCT_MMS_MEDIA, &media[0]);
	msg_set_int_value(media[0], MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_IMG);
	msg_set_str_value(media[0], MSG_MMS_MEDIA_REGION_ID_STR, (char *)"Image", 5);
	msg_set_str_value(media[0], MSG_MMS_MEDIA_FILEPATH_STR, (char *)"/opt/etc/msg-service/image.jpg",255);

	msg_mms_add_item(page[0], MSG_STRUCT_MMS_MEDIA, &media[1]);
	msg_set_int_value(media[1], MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_AUDIO);
	msg_set_str_value(media[1], MSG_MMS_MEDIA_FILEPATH_STR, (char *)"/opt/etc/msg-service/audio.amr",255);

	msg_mms_add_item(page[0], MSG_STRUCT_MMS_MEDIA, &media[2]);
	msg_set_int_value(media[2], MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_TEXT);
	msg_set_str_value(media[2], MSG_MMS_MEDIA_REGION_ID_STR, (char *)"Text", 4);
	msg_set_str_value(media[2], MSG_MMS_MEDIA_FILEPATH_STR, (char *)"/tmp/Temp0_2.txt", 255);

	//set smil text
	msg_get_struct_handle(media[2], MSG_MMS_MEDIA_SMIL_TEXT_HND, &smil_text[0]);

	msg_set_int_value(smil_text[0], MSG_MMS_SMIL_TEXT_COLOR_INT, 0x000000);
	msg_set_int_value(smil_text[0], MSG_MMS_SMIL_TEXT_SIZE_INT, MMS_SMIL_FONT_SIZE_NORMAL);
	msg_set_bool_value(smil_text[0], MSG_MMS_SMIL_TEXT_BOLD_BOOL, true);

	//page 1
	msg_mms_add_item(mms_data, MSG_STRUCT_MMS_PAGE, &page[1]);
	msg_set_int_value(page[1], MSG_MMS_PAGE_PAGE_DURATION_INT, 4544);

	msg_mms_add_item(page[1], MSG_STRUCT_MMS_MEDIA, &media[3]);
	msg_set_int_value(media[3], MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_TEXT);
	msg_set_str_value(media[3], MSG_MMS_MEDIA_REGION_ID_STR, (char *)"Text", 4);
	msg_set_str_value(media[3], MSG_MMS_MEDIA_FILEPATH_STR, (char *)"/opt/etc/msg-service/Temp1_0.txt", 255);

	//set smil text
	msg_get_struct_handle(media[3], MSG_MMS_MEDIA_SMIL_TEXT_HND, &smil_text[1]);

	msg_set_int_value(smil_text[1], MSG_MMS_SMIL_TEXT_COLOR_INT, 0x000000);
	msg_set_int_value(smil_text[1], MSG_MMS_SMIL_TEXT_SIZE_INT, MMS_SMIL_FONT_SIZE_NORMAL);
	msg_set_bool_value(smil_text[1], MSG_MMS_SMIL_TEXT_ITALIC_BOOL, true);

	msg_mms_add_item(page[1], MSG_STRUCT_MMS_MEDIA, &media[4]);
	msg_set_int_value(media[4], MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_VIDEO);
	msg_set_str_value(media[4], MSG_MMS_MEDIA_REGION_ID_STR, (char *)"Text", 4);
	msg_set_str_value(media[4], MSG_MMS_MEDIA_FILEPATH_STR, (char *)"/opt/etc/msg-service/video.3gp", 255);
	msg_set_str_value(media[4], MSG_MMS_MEDIA_ALTERNATIVE_STR, (char *)"Video Load Fail", 255);

	msg_set_mms_struct(msgInfo, mms_data);

	msg_release_struct(&mms_data);

	// Set Recipient Address
	char number[MAX_ADDRESS_VAL_LEN];

	memset(number, 0x00, MAX_ADDRESS_VAL_LEN);
	strncpy(number, "+821030011234", sizeof(number)-1);

	msg_struct_t tmpAddr;
	msg_list_add_item(msgInfo, MSG_MESSAGE_ADDR_LIST_HND, &tmpAddr);
	
	msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_TYPE_INT, MSG_ADDRESS_TYPE_PLMN);
	msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT, MSG_RECIPIENTS_TYPE_TO);
	msg_set_str_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, number, strlen(number));


	if (err != MSG_SUCCESS) goto free_memory;

	err = msg_add_message(hMsgHandle, msgInfo, sendOpt);

	if (err == MSG_SUCCESS)
		printf("Saving Message is OK!");
	else
		printf("Saving Message is failed!");

free_memory:
	msg_release_struct(&msgInfo);
	msg_release_struct(&sendOpt);
}
@endcode
@}

@defgroup MESSAGE_USECASES_4 Sending a SMS/MMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Sending a SMS/MMS Message</h3>

- int msg_sms_send_message(msg_handle_t handle, msg_struct_t req);
@n msg_sms_send_message() is a function to send SMS through messaging framework. The first parameter is the handle which is created by msg_open_msg_handle (). The second parameter is the structure that includes the message information to send. You can get the result of sending on sent status callback.

- int msg_mms_send_message(msg_handle_t handle, msg_struct_t req);
@n msg_sms_send_message() is a function to send MMS through messaging framework. The first parameter is the handle which is created by msg_open_msg_handle (). The second parameter is the structure that includes the message information to send. You can get the result of sending on sent status callback.
@code
#include <msg.h>
#include <msg_type.h>
#include <msg_transport.h>

int MsgTestSendMsg(MSG_HANDLE_T hMsgHandle, msg_struct_t pMsg)
{
	if (hMsgHandle == NULL)
	{
		printf("Handle is NULL\n");
		return MSG_ERR_NULL_MSGHANDLE;
	}

	MSG_ERROR_T err = MSG_SUCCESS;

	msg_struct_t pReq = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
	
	msg_set_struct_handle(pReq, MSG_REQUEST_MESSAGE_HND, pMsg);

	int msg_type;
	
	msg_get_int_value(pMsg, MSG_MESSAGE_TYPE_INT, &msg_type);

	if (msg_type == MSG_TYPE_MMS)
		err = msg_mms_send_message(hMsgHandle, pReq);
	else // SMS
		err = msg_sms_send_message(hMsgHandle, pReq);

	if (err == MSG_SUCCESS)
		printf("Request to Send Message is successful!!!");
	else
		printf("Request to Send Message is failed!!!");

	msg_release_struct(&pReq);

	return err;
}
@endcode
@}

@defgroup MESSAGE_USECASES_5 Sending Simple SMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Simple SMS Sending</h3>
- int msg_sms_send(const char *phone_num_list, const char *sms_text, msg_simple_sent_status_cb cb, void *user_param);
@n msg_sms_send() is a simple function to send an SMS message. Without this API, in order to send a message the application should allocate a channel with messaging daemon for IPC, register sent-status callback function to monitor the sending result, and fulfill many member variables of MSG_MESSAGE_S. This function implicitly makes a connection with messaging daemon and registers the callback function.
@code
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <msg_transport.h>

GMainLoop *mainloop;

typedef struct {
	char number[256];
	char text[256];
	char userdata[256];
} send_data;

void sent_status_cb(msg_struct_t sent_status, void *userData)
{
	int reqId, status;
	msg_error_t err = MSG_SUCCESS;
	
	err = msg_get_int_value(sent_status, MSG_SENT_STATUS_REQUESTID_INT, &reqId);
	err = msg_get_int_value(sent_status, MSG_SENT_STATUS_NETWORK_STATUS_INT, &status);
	
	if (status == MSG_NETWORK_SEND_SUCCESS)
		printf("reqId : %d  MSG SENT SUCCESS !!!\n", reqId);
	else
		printf("reqId : %d  MSG SENT FAIL !!! [%d]\n", reqId, status);
}

// count from here
gboolean send_func(gpointer data)
{
	send_data* sms_input = (send_data*)data;

	printf("Begin to send [%s] to [%s]\n", sms_input->number, sms_input->text);
	MSG_ERROR_T err = msg_sms_send(sms_input->number, sms_input->text, &sent_status_cb, (void*)sms_input->userdata);

	if (err != MSG_SUCCESS)
		printf("Send failed [%d]\n", err);

	return FALSE;
}
// end

int main(int argc, char* argv[])
{
	if (argc != 3 && argc != 4)
	{
		printf("Usage: %s  {phone_num_list} {sms_text} [user_data]\n", argv[0]);
		printf("phone_num_list: phone_num1, phone_num2, ..., phone_numN\n");
		return 0;
	}

	// Set sms input parameters : phone numbers and text
	send_data sms_input = {};
	strncpy(sms_input.number, argv[1], sizeof(sms_input.number)-1);
	strncpy(sms_input.text, argv[2], sizeof(sms_input.text)-1);
	if (argc == 4)
		strncpy(sms_input.userdata, argv[3], sizeof(sms_input.userdata)-1);

	// Add Sending Function to GMainLoop
	g_idle_add(&send_func, (gpointer) &sms_input);

	// start GMainLoop
	mainloop = g_main_loop_new(NULL, FALSE);

	printf("Entering GMain Loop to Receive Notifications in Thread...\n");

	g_main_loop_run(mainloop);

	printf("==== End Test App. Bye...===\n");

	return 0;
}
@endcode
@}

@defgroup MESSAGE_USECASES_6 Retrieving a MMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Retrieving a MMS Message</h3>
- int msg_mms_retrieve_message(msg_handle_t handle, msg_struct_t req);
@n msg_mms_retrieve_message() is a function to submit a retrieve MMS request.
@code
void MsgTestRetrieveMessage(MSG_HANDLE_T hMsgHandle, MSG_MESSAGE_ID_T nMsgId)
{
	if (hMsgHandle == NULL)
	{
		printf("Handle is NULL");
		return;
	}

	msg_error_t err = MSG_SUCCESS;

	msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
	msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);

	err = msg_get_message(hMsgHandle, nMsgId, msg, sendOpt);

	int msgId = 0;
	msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &msgId);
	msg_update_read_status(hMsgHandle, msgId, true);

	if( err != MSG_SUCCESS)
		print("Get Message Failed!");

	msg_struct_t req = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
	msg_set_struct_handle(req, MSG_REQUEST_MESSAGE_HND, msg);
	msg_set_struct_handle(req, MSG_REQUEST_SENDOPT_HND, sendOpt);

	err = msg_mms_retrieve_message(hMsgHandle, &req);

	if (err != MSG_SUCCESS)
		printf("Retrieve MMS Message Failed!");

	msg_release_struct(&msg);
	msg_release_struct(&sendOpt);
}
@endcode
@}

@defgroup MESSAGE_USECASES_7 Getting a SMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Getting a SMS Message</h3>
- int msg_get_message(msg_handle_t handle, msg_message_id_t msg_id, msg_struct_t msg, msg_struct_t send_opt);
@n msg_get_message() is a function to get a message. The first parameter is the handle which is created by msg_open_msg_handle (). The second parameter is the message ID you want to get. The third parameter is the message object to receive the message information. The last parameter is the structure to receive the message sending options.

- Enumeration with MSG_MESSAGE_ prefix in _MSG_MESSAGE_INFO_E_.
@n Enumerations to get and set message detail informations. 

@code
void MsgTestGetSmsMessage(MSG_HANDLE_T hMsgHandle, int MsgId)
{
	if (hMsgHandle == NULL)
	{
		printf("Handle is NULL\n");
		return;
	}

	msg_error_t err = MSG_SUCCESS;

	msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
	msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);

	err = msg_get_message(hMsgHandle, (msg_message_id_t)MsgId, msg, sendOpt);

	if (err != MSG_SUCCESS)
	{
		goto free_memory;
	}
	int msg_type = 0;
	msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &msg_type);
	// Update Read Status
	msg_update_read_status(hMsgHandle, MsgId, true);

free_memory:
	msg_release_struct(&msg);
	msg_release_struct(&sendOpt);
	
	return;
}
@endcode
@}

@defgroup MESSAGE_USECASES_8 Getting a MMS Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Getting a MMS Message</h3>
- int msg_get_message(msg_handle_t handle, msg_message_id_t msg_id, msg_struct_t msg, msg_struct_t send_opt);
@n msg_get_message() is a function to get a message. The first parameter is the handle which is created by msg_open_msg_handle (). The second parameter is the message ID you want to get. The third parameter is the message object to receive the message information. The last parameter is the structure to receive the message sending options.
- int msg_get_mms_struct(msg_struct_t msg_struct_handle, msg_struct_t mms_struct_handle);
@n msg_get_mms_struct() is a function to get a pointer of MMS structure in message. The second parameter is handle to MMS data structure.
@code
void MsgTestGetMmsMessage(MSG_HANDLE_T hMsgHandle, int MsgId)
{
	if (hMsgHandle == NULL)
	{
		MSG_DEBUG("Handle is NULL");
		return;
	}
	
	msg_error_t err = MSG_SUCCESS;
	
	msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
	msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
	
	
	err = msg_get_message(hMsgHandle, (msg_message_id_t)MsgId, msg, sendOpt);
	
	if (err != MSG_SUCCESS)
	{
		msg_release_struct(&msg);
		msg_release_struct(&sendOpt);
		return;
	}
	int msg_type = 0;
	msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &msg_type);
	// Update Read Status
	msg_update_read_status(hMsgHandle, MsgId, true);
	
	// Send Read Report
	if (msg_is_mms(msg_type))
	{
		int folder_id = 0;
		msg_get_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT, &folder_id);
		if (folder_id == MSG_INBOX_ID) {
			msg_mms_send_read_report(hMsgHandle, MsgId, MSG_READ_REPORT_IS_READ);
		}
	}
	
	msg_struct_t mms_struct = msg_create_struct(MSG_STRUCT_MMS);
	msg_get_mms_struct(pMsg, mms_struct);
	
	//Check MMS message data.
	
	msg_release_struct(&mms_struct);
	msg_release_struct(&msg);
	msg_release_struct(&sendOpt);
@endcode
@}

@defgroup MESSAGE_USECASES_9 Delete a Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Delete a Message</h3>
- int msg_delete_message(msg_handle_t handle, msg_message_id_t msg_id)
@n msg_delete_message() is a function to delete a message from message box by msg_id.
@code
void MsgTestDeleteMessage(msg_handle_t hMsgHandle, msg_message_id_t nMsgId)
{
	MSG_ERROR_T err;

	if (msg_delete_message(hMsgHandle, nMsgId) != MSG_SUCCESS)
		printf("Failed to delete Message");

}
@endcode
@}

@defgroup MESSAGE_USECASES_10 Set/Get Message Setting
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Set / Get Message setting</h3>
Setting API is used to set or to get the message setting options. Setting data structure includes various setting information and is shared between message application and messaging daemon.

- int msg_get_smsc_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_set_smsc_opt(msg_handle_t handle, msg_struct_t msg_struct);
@n These APIs get and set a SMSC option.
- int msg_get_cb_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_set_cb_opt(msg_handle_t handle, msg_struct_t msg_struct)
@n These APIs get and set a CB channel option.
- int msg_get_sms_send_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_set_sms_send_opt(msg_handle_t handle, msg_struct_t msg_struct);
@n These APIs get and set a SMS sending option.
- int msg_get_mms_send_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_set_mms_send_opt(msg_handle_t handle, msg_struct_t msg_struct);
@n These APIs get and set a MMS sending option.
- int msg_get_mms_recv_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_get_mms_recv_opt(msg_handle_t handle, msg_struct_t msg_struct);
@n These APIs get and set a MMS receiving option.
- int msg_get_push_msg_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_set_push_msg_opt(msg_handle_t handle, msg_struct_t msg_struct);
@n These APIs get and set a push message option.
- int msg_get_general_opt(msg_handle_t handle, msg_struct_t msg_struct);
- int msg_get_general_opt(msg_handle_t handle, msg_struct_t msg_struct);
@n These APIs get and set a general option.
@code

void MsgTestSettingGeneralOpt(MSG_HANDLE_T hMsgHandle)
{
	MSG_ERROR_T err = MSG_SUCCESS;
	
	msg_struct = msg_create_struct(MSG_STRUCT_SETTING_GENERAL_OPT);

	err = msg_get_general_opt(hMsgHandle, msg_struct);

	if (err == MSG_SUCCESS)
	{
		printf("Setting Config Data is OK!\n");
	}
	else
		printf("Setting Config Data is failed!\n");
		
	
	msg_set_bool_value(msg_struct, MSG_GENERAL_KEEP_COPY_BOOL, true);
	msg_set_int_value(msg_struct, MSG_GENERAL_ALERT_TONE_INT, MSG_ALERT_TONE_5MINS);
	msg_set_bool_value(msg_struct, MSG_GENERAL_BLOCK_UNKNOWN_NUMBER_BOOL, true);
	msg_set_bool_value(msg_struct, MSG_GENERAL_MSG_NOTIFICATION_BOOL, true);
	msg_set_bool_value(msg_struct, MSG_GENERAL_MSG_VIBRATION_BOOL, true);
	msg_set_bool_value(msg_struct, MSG_GENERAL_MSG_PREVIEW_BOOL, true);
	msg_set_bool_value(msg_struct, MSG_GENERAL_AUTO_ERASE_BOOL, true);
	msg_set_int_value(msg_struct, MSG_GENERAL_SMS_LIMIT_CNT_INT, 100);
	msg_set_int_value(msg_struct, MSG_GENERAL_MMS_LIMIT_CNT_INT, 50);

	err = msg_set_general_opt(hMsgHandle, msg_struct);

	if (err == MSG_SUCCESS)
		printf("Setting Config Data is OK!");
	else
		printf("Setting Config Data is failed!");
		
	msg_struct_release(&msg_struct);
	
}
@endcode
@}

@defgroup MESSAGE_USECASES_11 Filtering a Message
@ingroup MESSAGE_USECASES
@{
		<h3 class="pg">Filtering a Message</h3>
Messaging framework provides a filtering function for incoming message. New incoming message can be blocked (Move to spam-box or discard) by adding a filtering rule. A incoming message can be blocked by its originating address or by subject matching. If address matching filter rule is applied, only messages with exactly the same phone number can be blocked. Whereas, if a subject matching filter rule is applied, all messages that include the registered subject string might be blocked. An application can add or remove a filtering rule by calling msg_add_filter() or msg_delete_filter().

- int msg_add_filter(msg_handle_t handle, const msg_struct_t msg_struct_handle);
@n msg_add_filter() inserts a filtering rule to filter list.
- int int msg_delete_filter(msg_handle_t handle, msg_filter_id_t filter_id)
@n msg_delete_filter()removes a filtering rule from filter list by filter id
@code
void MsgTestAddFilter(msg_handle_t hMsgHandle)
{
	if (hMsgHandle == NULL)
	{
		printf("Handle is NULL");
		return;
	}

	MSG_ERROR_T err = MSG_SUCCESS;

	msg_struct_t address_filter = msg_create_struct(MSG_STRUCT_FILTER);
	msg_struct_t subject_filter = msg_create_struct(MSG_STRUCT_FILTER);

	// Add filter by address
	char strTemp[MAX_FILTER_VALUE_LEN];
	memset(&strTemp, 0x00, sizeof(strTemp));	
	strncpy(strTemp, "+821234567890", MAX_FILTER_VALUE_LEN);

	err = msg_set_str_value(address_filter, MSG_FILTER_VALUE_STR, strTemp, strlen(strTemp));
	err = msg_set_int_value(address_filter, MSG_FILTER_TYPE_INT, MSG_FILTER_BY_ADDRESS_SAME);	
	
	err = msg_add_filter(hMsgHandle, address_filter);

	if (err == MSG_SUCCESS)
		printf("msg_add_filter success");
	else
		printf("msg_add_filter fail - err [%d]", err);

	// Add filter by subject
	memset(&strTemp, 0x00, sizeof(strTemp));	
	strncpy(strTemp, "test filter, MAX_FILTER_VALUE_LEN);
	
	err = msg_set_str_value(subject_filter, MSG_FILTER_VALUE_STR, strTemp, strlen(strTemp));
	err = msg_set_int_value(subject_filter, MSG_FILTER_TYPE_INT, MSG_FILTER_BY_WORD);
	
	err = msg_add_filter(hMsgHandle, subject_filter);

	if (err == MSG_SUCCESS)
		printf("msg_add_filter success");
	else
		printf("msg_add_filter fail - err [%d]", err);

	msg_release_struct(&address_filter);
	msg_release_struct(&subject_filter);	

	return;
}

void MsgTestDeleteFilter(msg_handle_t hMsgHandle, msg_filter_id_t filterId)
{
	if (hMsgHandle == NULL)
	{
		printf("Handle is NULL");
		return;
	}

	MSG_ERROR_T err = MSG_SUCCESS;
	err = msg_delete_filter(hMsgHandle, filterId);

	if (MSG_SUCCESS == err)
	{
		printf("msg_delete_filter success");
	}
	else
	{
		printf("msg_delete_filter fail - err [%d]", err);
	}

	return;
}
@endcode
@}
*/

/**
@addtogroup MESSAGE
@{
	@defgroup MESSAGE_USECASES Use Cases
@}
*/
