#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/plat_inc.h"
#include    "../../../../plat/scf/src/include/scfpub.h"
/*------------------------------------------------*/
static struct	termio    prev_termio;
static int		timer100=0;
extern int		subSystemID;

/*------------------------------------------------*/
/*------------------------------------------------*/
extern int smpp_timer();
extern int smppEncodeSM();
extern int smppDecodeSM();
extern int pps_read_sysparam();
/*------------------------------------------------*/


static void
platInit()
{
    debug_init(); 
    mtp_shm_init(); 
    iptrMainInit(); 
    snmp_init(4957); 
	sccp_init();

    tcap_init(512);	
    xap_init(512);     
	scsm_init();
}   

void
ppsModuleProc()
{
   //struct timeval tmstart,tmend;
   
   iptrans_timer();
   snmp_timer();
   heartbeat_timer();
   debug_rt();  
   mtp3_proc();
   sccp_timer();
   smpp_timer();
   tcap_fsm();
   xap_fsm();   

   
   scsm();
   
}


void
SysGuard(int sig)
{
   struct timeval tm;
   char fname[]={"../log/logout.txt"};
   FILE *fp;

   fp = fopen(fname,"w");
   if(fp != NULL)
   {
      gettimeofday(&tm,NULL);
	  fprintf(fp,"====================================\n");
	  fprintf(fp,"pps restart for segementation fault!\n");
	  fprintf(fp,"log time   :  %s\n",ctime(&tm.tv_sec));
      fclose(fp);
   }
   fprintf(stderr,"Exception met, exit!\n");
   exit(1);
}

static void 
Terminate(int sig)
{
    int 			retval=0,loop=0;
    char 			tm_str[30];
	time_t          tn;


	tn = time(NULL);
    ioctl(0, TCGETA, prev_termio);
    retval = shmdt((char *) 0);
	printf("Service down at %s\n", GetAsciiTime(tm_str));

	pps_exit(1);
	loop = 0;

	while(loop<15)
	{
		loop++;
		ppsModuleProc();
		pps_proc();
		usleep(10);
	}

    exit(sig);
}    

void
FaultSignalProc(int sig)
{
    system("/usr/local/pps/bin/ppsd restart");
}

void 
SetFSMTimer()
{
    struct itimerval    *ptv, tv;

    ptv = (struct itimerval *) &tv;
    ptv->it_interval.tv_sec = SMMP_IT_INTERVAL_SEC;
    ptv->it_interval.tv_usec = SMMP_IT_INTERVAL_USEC/2;
    ptv->it_value. tv_sec = SMMP_IT_VALUE_SEC;
    ptv->it_value.tv_usec = SMMP_IT_VALUE_USEC/2;
    setitimer(ITIMER_REAL, ptv, NULL);
}



void 
PrepaidAction(int sig)        
{

    timer100++;
    ppsModuleProc();
}


void SetTerminate()
{
   struct termio ptermio;
   ioctl(0,TCGETA, &ptermio);
   ptermio.c_cc[VINTR]='\x03';
   ioctl(0,TCSETA, &ptermio);   
   signal(SIGINT , Terminate);
   signal(SIGTERM, Terminate);
}

void
SigactionPrepaid()
{
    struct sigaction action;

    action.sa_handler = PrepaidAction;
    action.sa_flags = SA_RESTART;
    sigemptyset(&action.sa_mask);
    sigaction(SIGALRM, &action, NULL);
/*
	actsegv.sa_handler = SysGuard;
	actsegv.sa_flags = SA_RESTART;
	sigemptyset(&actsegv.sa_mask);
	sigaction(SIGSEGV,&actsegv,NULL);
*/
}

void shortMessageTest()
{
	char	sm_in[32]="000001000000",sm_out[32]="",sm_res[32]="";
	smppEncodeSM(sm_in,sm_out,12);
	smppDecodeSM(sm_out,sm_res,11*8/7);
	printf("result: %s\n",sm_res);
}

int
main(int argc, char **argv)
{
    int                 retval=0;
    int                 err_flag = FALSE; 
    int                 main_state=0;
    struct timeval tmstart,tmend;
    u_long			    peerip,localip=0x018812ac;
    //u_char				buf[128];

    while ((retval = getopt(argc, argv, "dvcf:I:")) != -1)
        switch (retval) {
               case 'd':
                DaemonInit("ppsm", LOG_USER);
                break;
            case '?':
                err_flag = TRUE;
                break;
        }
    if (err_flag) {
        log_msg("Usage: %s [-d] [-c] [-f RAM file name] [-v]\n", "ppsm");
        log_msg("    -d                  with daemon mode");
        log_msg("    -c                  Cancel RAM data initialization");
        log_msg("    -f[RAM file name]   Load RAM file");
        log_msg("    -v                  print version information");
        exit(1);
    }

    printf("sizeof _tariff_private: %d\n",sizeof(_tariff_private));
	pps_read_sysparam(&subSystemID,&localip,&peerip);
	//printf("smpplength: %d\n",smppEncodeSM("49998,2006-07-01 @2004-09-14 11:08<-86755900093",buf));
	//
    while(TRUE) {
        switch( main_state ) {
            case 0:			     			    
	            platInit();

			    SetTermSignal(&prev_termio, (void *)Terminate);
				if(subSystemID)
				{
					 heartbeat_init(0x0901);
				}
				else
				{
					heartbeat_init(0x0900);
				}

                SetFSMTimer();
                SigactionPrepaid();
                main_state = 1;
			    gettimeofday(&tmstart,NULL);
				
				printf("sizeof(all data):		%d\n",  
						sizeof(_ram_data));
				printf("sizeof(tariff_data):		%d\n",  
						sizeof(_tariff_data));
				printf("sizeof(card_data):		%d\n",
						sizeof(_card_data));
				printf("sizeof(user_data):		%d\n",
						sizeof(_prepaid_data));
				printf("sizeof(_tariff_private):		%d\n",
						sizeof(_tariff_private));			
				printf("sizeof(_ram_data):		%d\n",
						sizeof(_state_machine));
				printf("sizeof(_prepaid_info):		%d\n",
						sizeof(_prepaid_info));
				printf("sizeof(_state_machine): %d\n",
						sizeof(_state_machine));
				printf("sizeof(stat): %d\n",
						sizeof(_pps_cdr_buffer) + sizeof(_pps_csta_buffer));
                break;
            case 1:
				ppsModuleProc();
                if (pps_init(100000,subSystemID,localip,peerip,"11200001")) {
					main_state = 2;
					gettimeofday(&tmend,NULL);
					printf("Take %ld senconds\n",
					tmend.tv_sec-tmstart.tv_sec);
//					shortMessageTest();
                } 
                break;
            case 2:
			    if(timer100%TIMER_ACTION_STATE==0)
				{
gettimeofday(&tmstart,NULL);
				    pps_proc();/* Normal state    */
gettimeofday(&tmend,NULL);
//printf("Plat takes : %.1fms\n", (tmend.tv_sec-tmstart.tv_sec)*1000+(tmend.tv_usec-tmstart.tv_usec)/1000.0);
   
				}
                break;
            default:
                main_state = 0;
                break;
        }
		usleep(10);
    } 
}
