#include    "../include/includes.h"
#include    "../include/ppsm.h"
#include    "../include/ramdata.h"
#include    "../include/ppsinf.h"
#include    "../include/message.h"
#include    "../include/iofunc.h"
#include    "../include/version.h"
#include    "../include/pps_public.h"
#include    "../include/cdrme.h"
#include 	"../include/param.h"

#include    "../include/plat_inc.h"

#include "../include/ppsMibTable.h"
#include "../include/mfunc.h"

extern int					logMsgFlag;
extern	PPSParamStruct		ppsParam;
extern	struct timeval 		tvnow;
extern _ram_data    		*ramshm_ptr;
extern 	_state_machine		*smshm_ptr;;
extern 	_tariff_private 	*blf_shmp;

extern  _prepaid_info	*getPrepaidInfo(_account_info *account);

#define	FREE_SMS_ACTIVE		0x01
#define	FREE_SMS_DEACTIVE	0xFE
static int isFreeServiceActived(_prepaid_info   *prepaidInfo)
{
	if(prepaidInfo->freeSMSActiveDays > 0)
		return TRUE;
	return FALSE;
}
static void setFreeServiceActived(_prepaid_info   *prepaidInfo)
{
	COSTable	*cosTableItem;
	u_char 		cosID,activeDays;
	
  	cosID = prepaidInfo->cos_id;
	cosTableItem = &ppsParam.ppsTables.cosTable[cosID];
	activeDays = cosTableItem->serviceControl[0].freeSMSActiveDays;
	
	if(prepaidInfo->mo_expiration_date < tvnow.tv_sec + activeDays * 24 *3600)
		prepaidInfo->mo_expiration_date = tvnow.tv_sec + activeDays * 24 *3600;
	if(prepaidInfo->mt_expiration_date < tvnow.tv_sec + activeDays * 24 *3600)
		prepaidInfo->mt_expiration_date = tvnow.tv_sec + activeDays * 24 *3600;

	prepaidInfo->freeSMSActiveDays = (activeDays <= 0?15:activeDays);
	
}

static void setFreeServiceDeactived(_prepaid_info   *prepaidInfo)
{
	prepaidInfo->freeSMSActiveDays = 0;
}


static int sendFreeServiceAlreadyActived(_state_data *shmp,_prepaid_info   *prepaidInfo)
{
	char msg[MAX_SMS_LEN*4] = {0};

	strcpy(msg, (char *)getSmsSentenceNative(0,SMS_FREE_SERVICE_ACTIVE_ALREADY));
	if(prepaidInfo->freeSMSActiveDays != 255)
		sprintf(msg+strlen(msg),".%s %d.",getSmsSentenceNative(0,SMS_FREE_SERVICE_VALID_DAYS_LEFT),prepaidInfo->freeSMSActiveDays);
	
	return smppSendMOSM((char *)shmp->caller_info.number, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg,strlen(msg),0);	
}

static int sendFreeServiceAlreadyDeactived(_state_data *shmp)
{
	char			msg[MAX_SMS_LEN*4] = {0};

	strcpy(msg, (char *)getSmsSentenceNative(0,SMS_FREE_SERVICE_DEACTIVE_ALREADY));
	return smppSendMOSM((char *)shmp->caller_info.number, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg, strlen(msg), 0);	
}

static int sendFreeServiceActived(_state_data *shmp,_prepaid_info   *prepaidInfo)
{
	char 			msg[MAX_SMS_LEN*4] = {0};
	char			dayTimeReadable[32]={0};

	
	ppsgetdaytime_readFormat(dayTimeReadable);		
	strcpy(msg, (char *)getSmsSentenceNative(0,SMS_FREE_SERVICE_ACTIVED_NOTIFY));
	sprintf(msg+strlen(msg)," %s %s.", (char *)getSmsSentenceNative(0,SMS_ON),dayTimeReadable);
	if(prepaidInfo->freeSMSActiveDays != 255)
		sprintf(msg+strlen(msg),"%s %d.", (char *)getSmsSentenceNative(0,SMS_FREE_SERVICE_VALID_DAYS_LEFT),prepaidInfo->freeSMSActiveDays);
	return smppSendMOSM((char *)shmp->caller_info.number, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg, strlen(msg), 0);	
}

static int sendFreeServiceDeactived(u_char *destNumber)
{
	char 			msg[MAX_SMS_LEN*4] = {0};
	char			dayTimeReadable[32]={0};

	
	ppsgetdaytime_readFormat(dayTimeReadable);	
	strcpy(msg, (char *)getSmsSentenceNative(0,SMS_FREE_SERVICE_DEACTIVED_NOTIFY));
	sprintf(msg+strlen(msg)," %s %s.", (char *)getSmsSentenceNative(0,SMS_ON),dayTimeReadable);
	return smppSendMOSM((char *)destNumber, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						,(u_char *)msg,strlen(msg),0);	
}

static int sendFreeServiceExpired(u_char *destNumber)
{
	char 			msg[MAX_SMS_LEN*4] = {0};
	char			dayTimeReadable[32]={0};

	ppsgetdaytime_readFormat(dayTimeReadable);
	strcpy(msg, (char *)getSmsSentenceNative(0,SMS_FREE_SERVICE_DEACTIVED_EXPIRED));
	sprintf(msg+strlen(msg)," %s %s.", (char *)getSmsSentenceNative(0,SMS_ON),dayTimeReadable);
	return smppSendMOSM((char *)destNumber, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg, strlen(msg), 0);	
}

static int sendFreeServiceInsufficientFee(u_char *destNumber)
{
	char 			msg[MAX_SMS_LEN*4] = {0};
	//char			dayTimeReadable[32]={0};

	sprintf(msg, " %s.", (char *)getSmsSentenceNative(0,SMS_INSUFFICIENT_FEE));
	return smppSendMOSM((char *)destNumber, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg, strlen(msg), 0);	
}

static int sendFreeServiceMoExpired(u_char *destNumber)
{
	char 			msg[MAX_SMS_LEN*4] = {0};
	//char			dayTimeReadable[32]={0};

	sprintf(msg," %s.", (char *)getSmsSentenceNative(0,SMS_EXPIRED_ACCOUNT));
	return smppSendMOSM((char *)destNumber, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg, strlen(msg), 0);	
}

static int sendFreeServiceErroCode(_state_data *shmp)
{
	char 			msg[MAX_SMS_LEN*4] = {0};
		
	sprintf(msg, " %s.", (char *)getSmsSentenceNative(0,SMS_FREE_SMS_NOTIFICATION));
	
	return smppSendMOSM((char *)shmp->caller_info.number, (char *)ppsParam.ppsTables.serviceNumber[FreeServicePosition].number
						, (u_char *)msg, strlen(msg), 0);	
	//return ;
}

static void enableUserRentFlag(_prepaid_info   *prepaidInfo)
{
	COSTable 	*cosTableItem;
	u8 			rentType;

	cosTableItem = &ppsParam.ppsTables.cosTable[prepaidInfo->cos_id];
	
	rentType = cosTableItem->serviceControl[0].freeSMSRentType;
	if(rentType <= 0)
		return; 
	rentType = (rentType - 1) & 0x07;
	prepaidInfo->rent_type |= (0x01 << rentType);
}

static void disableUserRentFlag(_prepaid_info   *prepaidInfo)
{
	COSTable 	*cosTableItem;
	u8			 rentType,mask = 0xFE;

	cosTableItem = &ppsParam.ppsTables.cosTable[prepaidInfo->cos_id];
	rentType = cosTableItem->serviceControl[0].freeSMSRentType;
	if(rentType <= 0)
		return; 
	rentType = (rentType - 1) & 0x07;
	mask = (mask >> (8-rentType)) | (mask << rentType);
	prepaidInfo->rent_type &= mask;
}

static int isFreeServiceDaysDeductable(_prepaid_info   *prepaidInfo)
{
	if(prepaidInfo->freeSMSActiveDays == 0xFF)
		return FALSE;
	return TRUE;
}

void freeServiceDaysDeduct(u_short head,u_short tail)
{
	u8				len;//cosID=0,
	//COSTable		*cosTableItem;
	 _prepaid_data   *shmp=&ramshm_ptr->prepaid_data;
	_prepaid_info 	*userData;
	u_char			destNumber[32]={0};

	userData = &shmp->prepaid_info[head][tail];
  	//cosID = userData->cos_id;
  	if(isFreeServiceActived(userData)== TRUE && isFreeServiceDaysDeductable(userData) == TRUE)
  	{
		//cosTableItem = &ppsParam.ppsTables.cosTable[cosID];
		userData->freeSMSActiveDays--;
		if(userData->freeSMSActiveDays <= 0)
		{
			disableUserRentFlag(userData);
			len = userData->msisdn[MAX_MSISDN_BLEN-1];
			BcdToAscii((char *)destNumber,userData->msisdn,(MAX_MSISDN_BLEN-1)*2);
			destNumber[len] = 0;
			sendFreeServiceExpired(destNumber);
		}
  	}			
}

int GetCosIDByUserData(u_short head,u_short tail)
{
	u8				cosID=0;
	COSTable		*cosTableItem;
	 _prepaid_data   *shmp=&ramshm_ptr->prepaid_data;
	_prepaid_info 	*userData;

	userData = &shmp->prepaid_info[head][tail];
  	cosID = userData->cos_id;
  	if(isFreeServiceActived(userData)== TRUE)
  	{
		cosTableItem = &ppsParam.ppsTables.cosTable[cosID];
		cosID = cosTableItem->serviceControl[0].relatedCosID;
  	}			
    return cosID%MaxCosTableItem;
}

int GetCosIDByAccount(_account_info *ptr)
{
    //_prepaid_data   *shmp=&ramshm_ptr->prepaid_data;
	u8				cosID=0;
	
	PutLogFunID("GetCosIDByAccount");

   	if (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT)
  	{
   		cosID = GetCosIDByUserData(ptr->head,ptr->tail);	
   	}
   	return cosID%MaxCosTableItem;
}

int GetLocalCosID(_account_info *ptr)
{	
	u8				cosID=0;
	//COSTable		*cosTableItem;
	 _prepaid_data   *shmp=&ramshm_ptr->prepaid_data;
	_prepaid_info 	*userData;

	userData = &shmp->prepaid_info[ptr->head][ptr->tail];
  	cosID = userData->cos_id%MaxCosTableItem;  
    return cosID;
}

int GetMOTariffIDWithFreeServiceControl(u_short head,u_short tail)
{
    //_prepaid_data   *shmp=&ramshm_ptr->prepaid_data;
	u8				cosID=0;
	COSTable		*cosTableItem;
	
	PutLogFunID("GetMOTariffDWithFreeServiceControl");

  	cosID = GetCosIDByUserData(head,tail);
	cosTableItem = &ppsParam.ppsTables.cosTable[cosID];
    
	return cosTableItem->tariff[0].moTariffID%MAX_ZONE_NUM;
}


int GetMTTariffIDWithFreeServiceControl(_account_info *ptr)
{
    //_prepaid_data   *shmp=&ramshm_ptr->prepaid_data;
	u8				cosID=0;
	COSTable		*cosTableItem;
	
	PutLogFunID("GetMOTariffDWithFreeServiceControl");

  	cosID = GetCosIDByAccount(ptr);
	cosTableItem = &ppsParam.ppsTables.cosTable[cosID];
    
	return cosTableItem->tariff[0].mtTariffID%MAX_ZONE_NUM;
}

void SendManualOperationCDR(_account_info *caller_info,_account_info *called_info,int charge)
{
    _tocdr_report  	pcdr;
    char           	buf[BUFSIZE]={""}; 
	int			   	balance,len;
	int			 	head, tail;
		
	PutLogFunID("SendManualOperationCDR");

	head = caller_info->head;
	tail = caller_info->tail;
	
    memset(&pcdr, 0, sizeof(_tocdr_report));
    if (charge >= 0)
	{
        pcdr.type[0] = CT_ASSISTED_UP;
		pcdr.type[1] = CT_ASSISTED_UP>>8;
	}
    else
	{
        pcdr.type[0] = CT_ASSISTED_DOWN;
		pcdr.type[1] = CT_ASSISTED_DOWN>>8;
	}

    AsciiToBcd(pcdr.seizuretime, ppsgetdaytime(buf), 14);
    AsciiToBcd(pcdr.answertime, ppsgetdaytime(buf), 14);
    AsciiToBcd(pcdr.releasetime, ppsgetdaytime(buf), 14); 
    pcdr.duration[0] = 0;
	charge = abs(charge);
    memcpy(pcdr.charge,&charge,4);
    balance = (int) GetAccountBalance(head, tail);
    memcpy(pcdr.balance,&balance,4);

    GetAccountMsisdn(head,tail,&pcdr.msisdn[1]);
	ByteRev(pcdr.msisdn,9,0);

	pcdr.msisdn[0]=0x91;
	memcpy(pcdr.caller,pcdr.msisdn,9);
    buf[0] = 0;

	pcdr.called[0] = 0x91;	
	len = strlen((char *)called_info->number)%20;
	ppsAsciiToBcdR(&pcdr.called[1], (char *)called_info->number,(len+1)/2*2);
	if(len %2)
	{
		pcdr.called[(len+1)/2] |= 0xF0;
	}
	if(len<21)
	{
		pcdr.called[(len+1)/2+1] = 0xFF;
	}
			
	sprintf(buf,"FFFFFFFFFFFFFFFFFF");
    AsciiToBcd(pcdr.imsi,buf,16);
	
    pcdr.tcos[0] = NORMAL_CLEARING%256;

	CDRStatistics(&pcdr,charge, 0);
	StoreCDR(&pcdr);
	pps_real_update_user_file(head, tail);

#if DEBUG
   if((logMsgFlag & 0x04) || (logMsgFlag & 0x02))
    DebugMsg(debugmib.display.asciiOut, "SendManualOperationCDR");
#endif
}

static int activteCharge(_state_data *shmp)
{
	int				head,tail;
	int				amount,tariff_id=0;
	_prepaid_info	*ptr;

	PutLogFunID("activteCharge");

	head = shmp->caller_info.head;
	tail = shmp->caller_info.tail;
	
	if(head>=MSISDN_HEAD_NUM) 
		return 0;
	ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
	if(isFreeServiceActived(ptr) == TRUE)
		return 0;
	if(GetExpiration(&shmp->caller_info) <= tvnow.tv_sec)
		return -1;
	tariff_id = GetAccountZoneID(head,tail);
	if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) 
		tariff_id = 0;	
	amount = blf_shmp->comm_tariff[tariff_id].activeFreeSMSCharegeAmount;
	if((ptr->balance + ptr->overdraft) - amount < 0)
		return -2;
	enableUserRentFlag(ptr);
		
	ptr->balance -= amount;
	SendManualOperationCDR(&shmp->caller_info,&shmp->called_info,-amount);	
	return amount;
}

static int deactivteCharge(_state_data *shmp)
{
	int				head,tail;
	int				amount,tariff_id=0;
	_prepaid_info	*ptr;

	PutLogFunID("deactivteCharge");

	head = shmp->caller_info.head;
	tail = shmp->caller_info.tail;
	
	if(head>=MSISDN_HEAD_NUM) 
		return 0;
	ptr = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
	if(isFreeServiceActived(ptr) == FALSE)
		return 0;
	if(GetExpiration(&shmp->caller_info) <= tvnow.tv_sec)
		return -1;
	tariff_id = GetAccountZoneID(head,tail);
	if(tariff_id>=MAX_ZONE_NUM || tariff_id<0) 
		tariff_id = 0;	
	amount = blf_shmp->comm_tariff[tariff_id].deactiveFreeSMSCharegeAmount;
	if((ptr->balance + ptr->overdraft) - amount < 0)
		return -2;
	disableUserRentFlag(ptr);
	
	
	ptr->balance -= amount;
	SendManualOperationCDR(&shmp->caller_info,&shmp->called_info,-amount);	
	return amount;
}


int switchServiceProc(u_short portid,u_char *shortMsg)
{
	_prepaid_info 	*prepaidInfo;
	u8				len;
	int				charge;
	u_char			*sms;
	_state_data 	*shmp;
	
	PutLogFunID("switchServiceProc");

	shmp = (_state_data *)&smshm_ptr->state_data;
	shmp += portid;
	
	if((prepaidInfo = getPrepaidInfo(&shmp->caller_info)) == NULL)
		return -1;
	sms = getSmsSentenceNative(0,SMS_FREE_SERVICE_ACTIVE);
	len = strlen((char *)sms);
	if(!strncasecmp((char *)shortMsg, (char *)sms, len))
	{		
		if(isFreeServiceActived(prepaidInfo) == FALSE)
		{
			charge = activteCharge(shmp);
			if(charge < 0)
			{	switch(charge)
				{
					case -1:
						pps_print_error(shmp->process_info.logMsisdn,"[%05d]switch service,activate fail ,insufficient fee",portid);
						sendFreeServiceMoExpired(shmp->caller_info.number);
					break;
					case -2:						
						pps_print_error(shmp->process_info.logMsisdn,"[%05d]switch service,activate fail ,MO expired",portid);
						sendFreeServiceInsufficientFee(shmp->caller_info.number);
					break;
				}
				return -1;
			}
			setFreeServiceActived(prepaidInfo);				
			sendFreeServiceActived(shmp,prepaidInfo);
			SendAccountRealSync_2(&shmp->caller_info,-charge,0.0,OMC_OCODE_EDIT);
		}
		else
			sendFreeServiceAlreadyActived(shmp,prepaidInfo);
		return 1;
	}

	sms = getSmsSentenceNative(0,SMS_FREE_SERVICE_DEACTIVE);
	len = strlen((char *)sms);
	if(!strncasecmp((char *)shortMsg, (char *)sms, len))
	{
		if(isFreeServiceActived(prepaidInfo) == TRUE)
		{
			charge = deactivteCharge(shmp);
			if(charge < 0)
			{
				switch(charge)
				{
					case -1:
						pps_print_error(shmp->process_info.logMsisdn,"[%05d]switch service,deactivate fail ,insufficient fee",portid);
						sendFreeServiceMoExpired(shmp->caller_info.number);
					break;
					case -2:						
						pps_print_error(shmp->process_info.logMsisdn,"[%05d]switch service,deactivate fail ,MO expired",portid);
						sendFreeServiceInsufficientFee(shmp->caller_info.number);
					break;
				}
				return -1;
			}
			setFreeServiceDeactived(prepaidInfo);
			sendFreeServiceDeactived(shmp->caller_info.number);
			SendAccountRealSync_2(&shmp->caller_info,-charge,0.0,OMC_OCODE_EDIT);
		}
		else
			sendFreeServiceAlreadyDeactived(shmp);
		return 1;
	}	

	sms = getSmsSentenceNative(0,SMS_FREE_SERVICE_ENQUIRY);
	len = strlen((char *)sms);
	if(!strncasecmp((char *)shortMsg, (char *)sms, len))
	{
		if(isFreeServiceActived(prepaidInfo))
			sendFreeServiceAlreadyActived(shmp,prepaidInfo);
		else
			sendFreeServiceAlreadyDeactived(shmp);
		return 1;
	}	

	sendFreeServiceErroCode(shmp);
	
	return 1;	
}




