////////////////////////////////////////////////////////////////////////////////////////////
///////////////// This is ATMofBOA.c
///////////// It¡¯s ATM system, working in the user space in another board. 
//////////////////////////////////////////////////////////////////////////////////////////////
#include <pthread.h>
#include <rtai.h>
#include <rtai_lxrt.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <time.h>
RTIME period;
#define PORT1 2000
#define PORT2 1900
#define IPAD "10.3.52.16"
int checkflag=1;
struct depositor
{
	char num[20];   //account number
	char name[20];  //account name
	char per[20];	 //custom ID
	char sec[20];		 // account password
	float mon;		 // the amount of balance
};

struct depositor pass();
void menu();
void show(struct depositor) ;
float deposit(struct depositor );
float withdraw(struct depositor );
void showall(struct depositor );
void* sendsignal();// thread1

void error(const char *msg)
{
	perror(msg);
	exit(0);
}
void main(void) {


	struct depositor   Check;
	struct depositor   buffer;
	int n,sockfd;
	struct sockaddr_in server;
	period=start_rt_timer(nano2count(1000000));  // period is 1ms
	//socklen_t fromlen=sizeof(server);	// size of structure;;

	sockfd = socket(AF_INET,SOCK_STREAM, 0); // Creates socket. Connection based.
	if (sockfd < 0)                          // sock is the descriptor of this socket
		error("Error opening socket");

	bzero(&server,sizeof(server));			 // sets all values to zero.
	server.sin_family = AF_INET;		  // symbol constant for Internet domain
	server.sin_port = htons(PORT1);
	server.sin_addr.s_addr=inet_addr(IPAD); // here is the host IP

	if (connect(sockfd,(struct sockaddr *) &server,sizeof(struct sockaddr_in)) < 0)
		error("ERROR connecting");


	     pthread_t send_signal;
		 pthread_create(&send_signal,NULL,sendsignal,NULL);


	while(1)
	{

		Check=pass();
		//  printf("check the message number:%s\n",Check.num);
		// printf("check the message password:%s\n",Check.sec);
		strcpy(Check.name,"Check");

		// send message
		n= write(sockfd,&Check, sizeof(struct depositor));	// sendto() could be used.
		if (n < 0)
			error("ERROR writing to socket");

        printf("Waiting...\n");
		bzero(&buffer,sizeof(struct depositor));  //clear buffer
		n= read(sockfd,&buffer, sizeof(struct depositor));
		if (n < 0)
			 error("ERROR reading from socket");


		if(strcmp(buffer.num,"0000")==0) // Check the account # and password
		{
			printf("Wrong account number or password.");
			continue;
		}
		else      // if its correct
		{
			//printf("receive num	: %s\n",buffer.num);
		//	printf("receive name: %s\n",buffer.name);
			while(1)
			{
				menu();
				printf(" Please choose your operation:");
				scanf("%d",&n);
				if( n==4)
				{
					break;
				}
				switch(n)
				{
				case 1: show( buffer);break;
				case 2: buffer.mon=deposit( buffer);break;
				case 3: buffer.mon=withdraw( buffer);break;
				case 4: break;
				case 5: showall( buffer); break;
				case 0: checkflag=checkflag^1; break;
				default:  printf("Error number. Please choose again.\n ");
				}
				n= write(sockfd,&buffer, sizeof(struct depositor));	// sendto() could be used.
					if (n < 0)
					error("ERROR writing to socket");
			//		printf("send changing message name:%s", buffer.name);
			//		printf("send changing message money:%f", buffer.mon);
			}

		}
	}
	close(sockfd);
	pthread_join(sendsignal,NULL);
	return;
}
/////////////////////////////////////////////////////////
// this is a thread, send the check information to alarm
// when the communication is blocked
/////////////////////////////////////////////////////////
void* sendsignal()   // thread1
		{

	RT_TASK* rttask1 = rt_task_init(nam2num("thrd1"), 0, 512, 256);
	rt_task_make_periodic(rttask1, rt_get_time(), 2000*period);  /// per 2s
	int i=0;
	int n=0;
	char check='#';
    int sockfd;
    struct sockaddr_in thserver;
	sockfd = socket(AF_INET,SOCK_STREAM, 0); // Creates socket. Connection based.
	if (sockfd < 0)                          // sock is the descriptor of this socket
		error("Error opening socket");

	bzero(&thserver,sizeof(thserver));			 // sets all values to zero.
	thserver.sin_family = AF_INET;		  // symbol constant for Internet domain
	thserver.sin_port = htons(PORT2);
	thserver.sin_addr.s_addr=inet_addr(IPAD); // here is the host IP

	if (connect(sockfd,(struct sockaddr *) &thserver,sizeof(struct sockaddr_in)) < 0)
		error("ERROR connecting");
 // printf("im here come!\n");
  while(checkflag)
	{
		n= write(sockfd,&check, sizeof(check));
		if (n < 0)
		error("ERROR writing to socket");
	//	printf("Im sending check signal #\n");

		rt_task_wait_period();
	}
}



struct depositor pass()
				{
	struct depositor acp;
	bzero(&acp,sizeof(acp));
	printf("\n\n *************	Welcome to ATM of BOA   ******************* ");
	printf("\nPlease enter the account number:");
	scanf("%s",acp.num);
	printf("Please enter the password:");
	scanf("%s",acp.sec);
	return acp;
				}
void menu()  // show the menu
{

	printf("\n\n *************	Welcome to ATM of BOA   ******************* ");
	printf("\n                   1   Show the balance");
	printf("\n                   2   Deposit cash");
	printf("\n                   3   Withdraw cash");
	printf("\n                   4   Quit");
	printf("\n ************************************************************ \n");

}
void show(struct depositor buffer) // show the balance of the account
{

	{ printf("*************the balance of the account*********\n");
	printf("Balance: \n");
	printf("\n $%11.2f \n", buffer.mon);
	printf("**************************************************\n");
	}
}
float deposit(struct depositor dep)
{
	float cash;
	printf("Please enter the amount of cash to deposit:");
	scanf("%f", &cash);
	dep.mon+=cash;
	printf("\n Deposit cash successfully.\n");
	return dep.mon;

}
float withdraw(struct depositor dep)
{
	float cash;
	printf("Please enter the amount of cash to withdraw:");
	scanf("%f", &cash);
	if ((dep.mon)>=cash)
	{
		dep.mon-=cash;
	}
	else
	{
		printf("Sorry! Insufficient Balance!");
	}
	return dep.mon;
}
void showall(struct depositor dep) // show the balance of the account
{

	printf("the number(i) is %s\n", dep.num );
	printf("the name(i) is %s\n", dep.name );
	printf("the ID(i) is %s\n", dep.per );
	printf("the password(i) is %s\n", dep.sec );
	printf("the balance(i) is $%11.2f\n", dep.mon );
}
