#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

#include "./include/client.h"

#define  CLIENT_CFG	"./conf/smcli_client.cfg"

_client_param_t  client_cfg;

static int smcli_cmd_res=0;
static char smcli_result[256];

int client_read_conf()
{
	char s[80],s1[80];
	int  len;
	unsigned char conf_state=0xFF;
  	FILE *fpConf;
    
    	memset(&client_cfg, 0x00, sizeof(_client_param_t));
    	
	fpConf = fopen(CLIENT_CFG,"rb");
	
	if(fpConf == NULL)
	{
		return 0;
	}
   
	strcpy(s,"");
	strcpy(s1,"");
	while(fgets(s,1024,fpConf) !=(char *)0)
	{
		if( (int *)strchr(s,'#') !=NULL) continue;
		if( !strlen(s) ) continue;      
		len = strlen(s);
		if(len < 2) continue;
		
		if(s[len-1] == 0x0d ||s[len-1] == 0x0a)
		{
			if(s[len-2] == 0x0d ||s[len-2] == 0x0a)
			{
				s[len-2] = 0;
				len -= 2;			
			}
			else
			{
				s[len-1] = 0;
				len -= 1;
			}
		}

		if(!strncasecmp(s,"[EMS]",5))
		{
			conf_state = 0;
			continue;
		}
		else if(!strncasecmp(s,"[HSS]",5))
		{
			conf_state = 1;
			continue;
		}
		else if(!strncasecmp(s,"[AUC]",5))
		{
			conf_state = 2;
			continue;
		}
		else if(!strncasecmp(s,"[VMS]",5))
		{
			conf_state = 3;
			continue;
		}
		else if(!strncasecmp(s,"[Provision]",11))
		{
			conf_state = 4;
			continue;
		}

		switch(conf_state)
		{	
			case 0:
				if(strncasecmp(s,"ems0_ip=",8)==0)
	        		{
	        			client_cfg.ems_servers.host0_enable = 1;
	        			strcpy(client_cfg.ems_servers.host0_ip, &s[8]); 
	        			//host_ip = inet_addr(&s[8]);
	        		}
				else if(strncasecmp(s,"ems0_port=",10)==0)
	        		{
	        			client_cfg.ems_servers.host0_port = atoi(&s[10]);
	        		}
				else if(strncasecmp(s,"ems1_ip=",8)==0)
	        		{
	        			client_cfg.ems_servers.host1_enable = 1;
	        			strcpy(client_cfg.ems_servers.host1_ip, &s[8]); 
	        			//host_ip = inet_addr(&s[8]);
	        		}
				else if(strncasecmp(s,"ems1_port=",10)==0)
	        		{
	        			client_cfg.ems_servers.host1_port = atoi(&s[10]);
	        		}
				else if(strncasecmp(s,"user_name=",10)==0)
	        		{
	        			strcpy(client_cfg.ems_servers.user_name, &s[10]); 
	        		}				
				else if(strncasecmp(s,"password=", 9)==0)
	        		{
	        			strcpy(client_cfg.ems_servers.password, &s[9]); 
	        		}				
				else if(strncasecmp(s,"connect_hss=",12)==0)
	        		{
	        			client_cfg.connect_configured[SYS_T_HSS] = 1;
	        			strcpy(client_cfg.connect_command[SYS_T_HSS], &s[12]); 
	        		}
				else if(strncasecmp(s,"connect_auc=",12)==0)
	        		{
	        			client_cfg.connect_configured[SYS_T_AUC] = 1;	        		
	        			strcpy(client_cfg.connect_command[SYS_T_AUC], &s[12]); 
	        		}
				else if(strncasecmp(s,"connect_vms=",12)==0)
	        		{
	        			client_cfg.connect_configured[SYS_T_VMS] = 1;	
	        			strcpy(client_cfg.connect_command[SYS_T_VMS], &s[12]); 
	        		}
			break;
			case 1:		
	        		strcpy(client_cfg.cli_command[SYS_T_HSS], s); 				
			break;    
			case 2:
	        		strcpy(client_cfg.cli_command[SYS_T_AUC], s);
			break;
			case 3:
	        		strcpy(client_cfg.cli_command[SYS_T_VMS], s);				
			break;
			case 4:
				if(strncasecmp(s,"enable", 6) == 0)
				{
					client_cfg.provsioning_flag = 1;
				}
			break;
      		}
	}
	
	fclose(fpConf);
	
	return 1;
}

int rest_provsioning_enabled()
{
	return client_cfg.provsioning_flag;
}

int smcli_reset_result()
{
	smcli_cmd_res = 0;
}

int smcli_get_result(char* result_des)
{
	if(smcli_cmd_res != 0)
		strcpy(result_des, smcli_result);
	
	return smcli_cmd_res;
}

int smcli_connect_ems()
{
	if(client_cfg.ems_servers.host0_enable)	
		tcp_connect_server(client_cfg.ems_servers.host0_ip, client_cfg.ems_servers.host0_port);
	else if(client_cfg.ems_servers.host1_enable)	
		tcp_connect_server(client_cfg.ems_servers.host1_ip, client_cfg.ems_servers.host1_port);

	return 1;
}

void	smcli_send_user_name_pwd(int flag)
{
	char user_name[128];
	char  password[128];

	if(flag == 0)
	{
		sprintf(user_name, "%s\r\n", client_cfg.ems_servers.user_name);
		tcp_send_msg(user_name, strlen(user_name));
	}
	else
	{
		sprintf(password, "%s\r\n", client_cfg.ems_servers.password);
		tcp_send_msg(password, strlen(password));
	}
}


void smcli_connect_cn_nodes(int sys_type)
{
	char command[128];
	
	sprintf(command, "%s\r\n", client_cfg.connect_command[sys_type]);
	tcp_send_msg(command, strlen(command));

}

void smcli_send_command(char *command)
{
	tcp_send_msg(command, strlen(command));
	
	smcli_reset_result();

}

void		crm_create_vms_account(char *number)
{
	char cli_command[1024];

	sprintf(cli_command,"create vmsSubscriber -msisdn %s", number);

	smcli_send_command(cli_command);
}

void crm_prov_hlr_auc_vms_account(char sub_data[][1024])
{//PRE_ID, IMSI, SERVICE_NBR, KI, OPC, ACCT_TYPE,CUST_ID, ACCT_ID, PRD_INST_ID, MOBILE_TYPE, VMS_FLAG
	char cli_command[1024];

	if(1)//HLR
	{
		sprintf(cli_command,"create subscriber -imsi %s -msisdn %s -eps_user_tpl def_eps -impi %s@ims.mnc010.mcc505.3gppnetwork.org",
			sub_data[2], sub_data[3], sub_data[2]);

		smcli_send_command(cli_command);
	}

	sleep(2);
	if(1)
	{
		if(sub_data[5][0] == 0)
			sprintf(cli_command,"create aucSubscriber -imsi %s -ki %s", sub_data[2], sub_data[4]);
		else
			sprintf(cli_command,"create aucSubscriber -imsi %s -ki %s -opc %s", sub_data[2], sub_data[4], sub_data[5]);

		smcli_send_command(cli_command);
	}

	sleep(2);
	
	if(atoi(sub_data[10]))//VMS enabled
	{
		crm_create_vms_account(sub_data[3]);
	}
	
}

int   smcli_link_fsm()
{
	u_char	recvbuf[1024];
	int		len = 0;
	
	int state = 0;

	state = client_cfg.smcli_link_state;
	
	switch(state)
	{
		case 0: //do nothing
		break;
		case 1:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf, "username:"))
				{
					smcli_send_user_name_pwd(0);
				}
							
				//if(strstr(recvbuf, "Welcome to"))
				client_cfg.smcli_link_state = 2;		
			}
		break;
		case 2:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf, "username:"))
				{
					smcli_send_user_name_pwd(0);
				}
				else if(strstr(recvbuf,"password:"))
				{
					smcli_send_user_name_pwd(1);
					client_cfg.smcli_link_state = 3;
					client_cfg.smcli_verified = 1;
				}
				else if(strstr(recvbuf, "Login incorrect"))
				{
					printf("error username/password\r\n");
					exit(128);
				}
			}
		break;
		case 3:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"CLI>")) //login succeed
				{
					client_cfg.smcli_link_state = 10;
				}
			}						
			break;
		case 10:
			if(client_cfg.connect_configured[SYS_T_HSS])
			{
				smcli_connect_cn_nodes(SYS_T_HSS);
				client_cfg.smcli_link_state = 11;			
			}
			else
			{
				client_cfg.smcli_link_state = 20;	
			}
				
		break;
		case 11:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"Login incorrec"))
				{
					printf("connect hlr failed\r\n");
				}
				client_cfg.smcli_link_state = 12;
			}			
		break;
		case 12:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"CLI>")) //input mode
				{
					client_cfg.smcli_link_state = 20;
				}
			}									
		break;
		case 20:
			if(client_cfg.connect_configured[SYS_T_AUC])
			{
				smcli_connect_cn_nodes(SYS_T_AUC);
				client_cfg.smcli_link_state = 21;	
			}
			else
			{
				client_cfg.smcli_link_state = 30;				
			}
		break;
		case 21:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"Login incorrec") )
				{
					printf("connect auc failed\r\n");
				}
				client_cfg.smcli_link_state = 22;
			}			
		break;
		case 22:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"CLI>")) //input mode
				{
					client_cfg.smcli_link_state = 30;//100;
				}
			}												
		break;
		case 30:
			if(client_cfg.connect_configured[SYS_T_VMS])
			{
				smcli_connect_cn_nodes(SYS_T_VMS);
				client_cfg.smcli_link_state = 31;			
			}
			else
			{
				client_cfg.smcli_link_state = 100;				
			}
			
		break;
		case 31:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"Login incorrec") )
				{
					printf("connect vms failed\r\n");
				}
				client_cfg.smcli_link_state = 32;
			}			
		break;
		case 32:
			len = tcp_recv_msg(recvbuf);
			if(len>0)
			{
				if(strstr(recvbuf,"CLI>")) //input mode
				{
					client_cfg.smcli_link_state = 100;
				}
			}												
		break;

		case 100://normal state, can handle cli command
			len = tcp_recv_msg(recvbuf);
			if(len>6)
			{
				if(strstr(recvbuf,"Login incorrect"))
				{
					printf("smcli link is discounneted\r\n");
					client_cfg.smcli_link_state = 1;				

					smcli_cmd_res = 2;
					strcpy(smcli_result, recvbuf);					
				}
				else if(strstr(recvbuf, "success"))
				{
					smcli_cmd_res = 1;
					strcpy(smcli_result, recvbuf);					
				}
				else 
				{
					smcli_cmd_res = 2;
					strcpy(smcli_result, recvbuf);					
				}
			}			
		
		break;
		
	}

	return state;
}

void smlci_connection_check()
{
	if(client_cfg.client_connected == 1)
		return;
	
	if(is_tcp_connected()>=0)
	{
		client_cfg.client_connected = 1;
		client_cfg.smcli_link_state = 1;
	}
}

void smcli_connection_is_broken()
{
	client_cfg.client_connected = 0;

	client_cfg.smcli_link_state = 0;	
	client_cfg.smcli_verified = 0;
	
}

int smcli_client_thread(void *param)
{
	static int smcli_timer= 0;
	
	client_read_conf();

	smcli_connect_ems();

	while(1)
	{
		if(smcli_timer % 10000)
		{
			tcp_check_connection();

			smlci_connection_check();
			smcli_timer = 0;	
		}

		smcli_link_fsm();
		
		smcli_timer ++;
		usleep(10000);
	}
	
	return 1;
}
