#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include "../include/restapi.h"

#define ENCODE_HEADER() \
do{ \
	buf[len++] = ptr->msg_type;	\
	buf[len++] = IE_SRC_REF;	\
	buf[len++] = 0x02;		\
	*(u16*)(&buf[len]) = htons(ptr->header.src_ref); \
	len += 2;			\
	buf[len++] = IE_DST_REF;	\
	buf[len++] = 0x02;		\
	*(u16*)(&buf[len]) = htons(ptr->header.dst_ref); \
	len += 2;			\
}while(0)

int encode_rest_query(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query.msisdn);
	len += vallen;
	
	return len;
}

static int decode_rest_query(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.query.msisdn, &buf[offset], vallen);
			ptr->msg.query.msisdn[vallen] = '\0';
			break;
		case IE_RESULT: 
			ptr->msg.query_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.query_res.error_code = buf[offset];
			break;
		case IE_BALANCE:
			ptr->msg.query_res.balance = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MO_EXPIRY:
			ptr->msg.query_res.mo_expiry = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MT_EXPIRY:
			ptr->msg.query_res.mt_expiry = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_USERNAME:
			{
				memcpy(ptr->msg.topup.username, &buf[offset], vallen);
				ptr->msg.topup.username[vallen] = '\0';
			}
			break;
		case IE_PASSWORD:
			{
				memcpy(ptr->msg.topup.password, &buf[offset], vallen);
				ptr->msg.topup.password[vallen] = '\0';
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

int encode_rest_query_res(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_res.result;
	if(ptr->msg.query_res.result == 1)
	{
		buf[len++] = IE_ERROR_CODE;
		buf[len++] = 0x01;
		buf[len++] = ptr->msg.query_res.error_code;
		
		return len;
	}

	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	// memcpy(&buf[len], &ptr->msg.query_res.balance, 0x04);
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_res.balance);
	len += 0x04;

	buf[len++] = IE_MO_EXPIRY;
	buf[len++] = 0x04;
	// memcpy(&buf[len], &ptr->msg.query_res.mo_expiry, 0x04);
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_res.mo_expiry);
	len += 0x04;

	buf[len++] = IE_MT_EXPIRY;
	buf[len++] = 0x04;
	// memcpy(&buf[len], &ptr->msg.query_res.mt_expiry, 0x04);
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_res.mt_expiry);
	len += 0x04;
	
	return len;
}

int encode_rest_topup(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.topup.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.topup.msisdn);
	len += vallen;

	buf[len++] = IE_USERNAME;
	vallen = strlen(ptr->msg.topup.username);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.topup.username);
	len += vallen;
	

	buf[len++] = IE_PASSWORD;
	vallen = strlen(ptr->msg.topup.password);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.topup.password);
	len += vallen;
	
	return len;
}

static int decode_rest_topup(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			{
				memcpy(ptr->msg.topup.msisdn, &buf[offset], vallen);
				ptr->msg.topup.msisdn[vallen] = '\0';
			}
			break;
		case IE_RESULT: 
			{
				ptr->msg.topup_res.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.topup_res.error_code = buf[offset];
			}
			break;
		case IE_BALANCE:
			{
				ptr->msg.topup_res.balance = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_MO_EXPIRY:
			{
				ptr->msg.topup_res.mo_expiry = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_MT_EXPIRY:
			{
				ptr->msg.topup_res.mt_expiry = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_USERNAME:
			{
				memcpy(ptr->msg.topup.username, &buf[offset], vallen);
				ptr->msg.topup.username[vallen] = '\0';
			}
			break;
		case IE_PASSWORD:
			{
				memcpy(ptr->msg.topup.password, &buf[offset], vallen);
				ptr->msg.topup.password[vallen] = '\0';
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

int encode_rest_topup_res(_rest_msg_s *ptr, u8 *buf)
{
	return encode_rest_query_res(ptr, buf);		
}

int decode_rest_transfer_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT: 
			{
				ptr->msg.transfer_rsp.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.transfer_rsp.error_code = buf[offset];
			}
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

// for selfcare======================================
int encode_rest_send_authcode_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	// IE_MSISDN
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.send_authcode_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.send_authcode_req.msisdn);
	len += vallen;

	// IE_MSG_CONTENT
	buf[len++] = IE_MSG_CONTENT;
	vallen = strlen(ptr->msg.send_authcode_req.sms_content);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.send_authcode_req.sms_content);
	len += vallen;
	
	return len;
}

int encode_rest_send_authcode_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.send_authcode_rsp.result;
	
	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.send_authcode_rsp.error_code);
	len += 0x04;

	return len;
}


int encode_rest_query_user_data_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_user_data_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_req.msisdn);
	len += vallen;
	
	return len;
}

int encode_rest_query_user_data_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_user_data_rsp.result;
	
	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.error_code);
	len += 0x04;

	// IE_MSISDN
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_user_data_rsp.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_rsp.msisdn);
	len += vallen;
	//
	
	// IE_REMARK
	buf[len++] = IE_REMARK;
	vallen = strlen(ptr->msg.query_user_data_rsp.remark);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_rsp.remark);
	len += vallen;
	//
	
	// IE_GROUP_NAME
	buf[len++] = IE_GROUP_NAME;
	vallen = strlen(ptr->msg.query_user_data_rsp.usrGrpName);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_rsp.usrGrpName);
	len += vallen;
	//
	
	// IE_STATUS
	buf[len++] = IE_STATUS;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_user_data_rsp.status;
	//

	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.balance);
	len += 0x04;
	//

	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.query_user_data_rsp.mo_expiry >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.mo_expiry & 0xFFFFFFFF);
	len += 0x04;
	//
	
	// IE_REMAIN_MO_VOICE_MIN
	buf[len++] = IE_REMAIN_MO_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_mo_voc_min);
	len += 0x04;
	//
	
	// IE_REMAIN_MT_VOICE_MIN
	buf[len++] = IE_REMAIN_MT_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_mt_voc_min);
	len += 0x04;
	//
	
	// IE_REMAIN_SMS_NUM
	buf[len++] = IE_REMAIN_SMS_NUM;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_sms_num);
	len += 0x04;
	//
	
	// IE_REMAIN_DATA_VOL_MB
	buf[len++] = IE_REMAIN_DATA_VOL_MB;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_data_vol);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_bundle_subs_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.bundle_subs_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.bundle_subs_req.msisdn);
	len += vallen;
	
	// IE_PAY_TYPE
	buf[len++] = IE_PAY_TYPE;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.bundle_subs_req.payType;
	//

	// IE_AMOUNT
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.charge);
	len += 0x04;
	//

	// IE_MO_VOICE_MIN
	buf[len++] = IE_MO_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.moVoiceMinute);
	len += 0x04;
	//
	
	// IE_MT_VOICE_MIN
	buf[len++] = IE_MT_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.mtVoiceMinute);
	len += 0x04;
	//
	
	// IE_SMS_NUM
	buf[len++] = IE_SMS_NUM;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.smsNum);
	len += 0x04;
	//
	
	// IE_DATA_VOL_MB
	buf[len++] = IE_DATA_VOL_MB;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.dataVolume);
	len += 0x04;
	//
	
	// IE_VALID_DAYS
	buf[len++] = IE_VALID_DAYS;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.validDays);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_bundle_subs_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.bundle_subs_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_rsp.error_code);
	len += 0x04;

	return len;
}

int encode_rest_bundle_usage_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.bundle_usage_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.bundle_usage_req.msisdn);
	len += vallen;
	
	return len;
}

int encode_rest_bundle_usage_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.bundle_usage_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.error_code);
	len += 0x04;

	// IE_REMAIN_MO_VOICE_MIN
	buf[len++] = IE_REMAIN_MO_VOICE_SEC;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.moVoiceInSec);
	len += 0x04;
	//
	
	// IE_REMAIN_MT_VOICE_MIN
	buf[len++] = IE_REMAIN_MT_VOICE_SEC;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.mtVoiceInSec);
	len += 0x04;
	//
	
	// IE_REMAIN_SMS_NUM
	buf[len++] = IE_REMAIN_SMS_NUM;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.smsNum);
	len += 0x04;
	//
	
	// IE_REMAIN_DATA_VOL_MB
	buf[len++] = IE_REMAIN_DATA_VOL_KB;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.dataVolInKB);
	len += 0x04;
	//
	
	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.bundle_usage_rsp.expiredTime >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.expiredTime & 0xFFFFFFFF);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_recharge_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.recharge_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.recharge_req.msisdn);
	len += vallen;
	
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_req.amount);
	len += 0x04;
	
	return len;
}

int encode_rest_recharge_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.recharge_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_rsp.error_code);
	len += 0x04;

	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_rsp.balance);
	len += 0x04;
	//
	
	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.recharge_rsp.expiredTime >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_rsp.expiredTime & 0xFFFFFFFF);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_transfer_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN_TRANS_OUT;
	vallen = strlen(ptr->msg.transfer_req.transferOutMsisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.transfer_req.transferOutMsisdn);
	len += vallen;
	
	buf[len++] = IE_MSISDN_TRANS_IN;
	vallen = strlen(ptr->msg.transfer_req.transferInMsisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.transfer_req.transferInMsisdn);
	len += vallen;
	
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transfer_req.amount);
	len += 0x04;
	
	return len;
}

int encode_rest_transfer_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.transfer_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transfer_rsp.error_code);
	len += 0x04;

	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transfer_rsp.balance);
	len += 0x04;
	
	return len;
}

int encode_rest_recharge_card_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.recharge_card_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.recharge_card_req.msisdn);
	len += vallen;
	
	buf[len++] = IE_PASSWORD;
	vallen = strlen(ptr->msg.recharge_card_req.cardPwd);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.recharge_card_req.cardPwd);
	len += vallen;
	
	return len;
}

int encode_rest_recharge_card_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.recharge_card_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.error_code);
	len += 0x04;

	// IE_BALANCE
	buf[len++] = IE_RECHARGE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.rechargeAmount);
	len += 0x04;
	//
	
	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.balance);
	len += 0x04;
	//
	
	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.recharge_card_rsp.expiredTime >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.expiredTime & 0xFFFFFFFF);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_check_balance_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.check_balance_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.check_balance_req.msisdn);
	len += vallen;
	
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.check_balance_req.amount);
	len += 0x04;
	
	return len;
}

int encode_rest_check_balance_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.check_balance_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.check_balance_rsp.error_code);
	len += 0x04;

	// IE_BALANCE_AVAILABLE
	buf[len++] = IE_BALANCE_AVAILABLE;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.check_balance_rsp.available;
	//
	
	return len;
}

int encode_rest_query_balance_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_balance_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_balance_req.msisdn);
	len += vallen;
	
	return len;
}

int encode_rest_query_balance_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_balance_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_balance_rsp.error_code);
	len += 0x04;

	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_balance_rsp.balance);
	len += 0x04;
	//
	
	return len;
}

static int decode_rest_send_authcode_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.send_authcode_req.msisdn, &buf[offset], vallen);
			ptr->msg.send_authcode_req.msisdn[vallen] = '\0';
			break;
		case IE_MSG_CONTENT:
			{
				int sms_len = vallen;
				if (sms_len > 127)
				{
					sms_len = 127;
				}
				memcpy(ptr->msg.send_authcode_req.sms_content, &buf[offset], sms_len);
				ptr->msg.send_authcode_req.sms_content[sms_len] = '\0';
			}
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_query_user_data_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.query_user_data_req.msisdn, &buf[offset], vallen);
			ptr->msg.query_user_data_req.msisdn[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_bundle_subs_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.bundle_subs_req.msisdn, &buf[offset], vallen);
			ptr->msg.bundle_subs_req.msisdn[vallen] = '\0';
			break;
		case IE_PAY_TYPE: 
			ptr->msg.bundle_subs_req.payType = buf[offset];
			break;
		case IE_AMOUNT:
			ptr->msg.bundle_subs_req.charge = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MO_VOICE_MIN:
			ptr->msg.bundle_subs_req.moVoiceMinute = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MT_VOICE_MIN:
			ptr->msg.bundle_subs_req.mtVoiceMinute = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_DATA_VOL_MB:
			ptr->msg.bundle_subs_req.dataVolume = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_SMS_NUM:
			ptr->msg.bundle_subs_req.smsNum = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_VALID_DAYS:
			ptr->msg.bundle_subs_req.validDays = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_bundle_usage_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.bundle_usage_req.msisdn, &buf[offset], vallen);
			ptr->msg.bundle_usage_req.msisdn[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_recharge_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.recharge_req.msisdn, &buf[offset], vallen);
			ptr->msg.recharge_req.msisdn[vallen] = '\0';
			break;
		case IE_AMOUNT:
			ptr->msg.recharge_req.amount = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_transfer_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN_TRANS_OUT:
			memcpy(ptr->msg.transfer_req.transferOutMsisdn, &buf[offset], vallen);
			ptr->msg.transfer_req.transferOutMsisdn[vallen] = '\0';
			break;
		case IE_MSISDN_TRANS_IN:
			{
				int num_len = vallen;
				if (num_len > 20)
				{
					num_len = 20;
				}
				memcpy(ptr->msg.transfer_req.transferInMsisdn, &buf[offset], num_len);
				ptr->msg.transfer_req.transferInMsisdn[num_len] = '\0';
			}
			break;
		case IE_AMOUNT:
			ptr->msg.transfer_req.amount = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_recharge_card_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.recharge_card_req.msisdn, &buf[offset], vallen);
			ptr->msg.recharge_card_req.msisdn[vallen] = '\0';
			break;
		case IE_PASSWORD:
			{
				int pwd_len = vallen;
				if (pwd_len > 20)
				{
					pwd_len = 20;
				}
				memcpy(ptr->msg.recharge_card_req.cardPwd, &buf[offset], pwd_len);
				ptr->msg.recharge_card_req.cardPwd[pwd_len] = '\0';
			}
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_check_balance_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.check_balance_req.msisdn, &buf[offset], vallen);
			ptr->msg.check_balance_req.msisdn[vallen] = '\0';
			break;
		case IE_AMOUNT:
			ptr->msg.check_balance_req.amount = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_query_balance_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.query_balance_req.msisdn, &buf[offset], vallen);
			ptr->msg.query_balance_req.msisdn[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}
//

int decode_rest_api_msg(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;

	if (len <= 9)
	{
		return -1;
	}

	ptr->msg_type = buf[offset++];

	switch (ptr->msg_type)
	{
	case REST_QUERY:
		decode_rest_query(buf+1, len-1, ptr);
		break;
	case REST_TOPUP:
		decode_rest_topup(buf+1, len-1, ptr);
		break;
	case REST_TRANSFER:
		decode_rest_transfer_res(buf+1, len-1, ptr);
		break;
	// for selfcare
	case REST_SEND_AUTHCODE_REQ:
		decode_rest_send_authcode_req(buf+1, len-1, ptr);
		break;
	case REST_QUERY_USERDATA_REQ:
		decode_rest_query_user_data_req(buf+1, len-1, ptr);
		break;
	case REST_BUNDLE_SUBS_REQ:
		decode_rest_bundle_subs_req(buf+1, len-1, ptr);
		break;
	case REST_BUNDLE_USAGE_REQ:
		decode_rest_bundle_usage_req(buf+1, len-1, ptr);
		break;
	case REST_RECHARGE_REQ:
		decode_rest_recharge_req(buf+1, len-1, ptr);
		break;
	case REST_TRANSFER_REQ:
		decode_rest_transfer_req(buf+1, len-1, ptr);
		break;
	case REST_RECHARGE_CARD_REQ:
		decode_rest_recharge_card_req(buf+1, len-1, ptr);
		break;
	case REST_CHECK_BALANCE_REQ:
		decode_rest_check_balance_req(buf+1, len-1, ptr);
		break;
	case REST_QUERY_BALANCE_REQ:
		decode_rest_query_balance_req(buf+1, len-1, ptr);
		break;
	//
	default:
		break;
	}
	
	return retval;
}

