//======================================================
//Each child board has a program
//They are the same except the index and the port number
//Here is the code for child board <1>
//======================================================
//For TCP image transmit
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#define MAXSIZE 1000

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

#include "errno.h"
#include "sys/types.h"

#include "netinet/in.h"
#include "sys/wait.h"

#include <pthread.h>    //header for creating threads
#include <sys/time.h>   //header for time
#include <fcntl.h>

#include <semaphore.h>  //header for semaphores
#include "rtai.h"       //headers for rtai
#include "rtai_lxrt.h"
#include "rtai_sched.h"
#include "sys/time.h"    //header for time

#include <recognition.h>    //header for character recognition
#include <chenLeeCV.h>      //for ClImage structure
#define STANDARD_WIDTH 32

//shared memory
 int num1, num2, num3, num4; int copy;
 int flag_received_segment= 0;

 //Computer Vision functions
 int SVM_Recognition(unsigned char* segment)
 {
    int result;
	ClImage Segment;
	Segment->imageData= segment;
	Segment->width= STANDARD_WIDTH;
	Segment->channels= 8;
	
    configureSystem(&gst);
    initSystem(&gst,svm);
    result= svmTestCharacter(&gst,svm, Segment, k);
   
    return result;
 }

 void SendNumber1(int num)
  {
	    //send recognized number to the main board(as server)
	     int sockfd, new_fd;
	     struct sockaddr_in my_addr;
	     struct sockaddr_in their_addr;
	     unsigned int sin_size,myport,listnum;
	     myport = 2001;
	     listnum = 10; //maximum listening number > number of characters in a plate

	     if((sockfd = socket(PF_INET,SOCK_STREAM, 0)) == -1 )
	     {
	         perror("socket is error/n;");
	         exit(1);
	     }
	     my_addr.sin_family = PF_INET;
	     my_addr.sin_port = htons(myport);
	     my_addr.sin_addr.s_addr = INADDR_ANY;  //my ip address
	     bzero(&(my_addr.sin_zero),0);

	     //=====================================================
	     their_addr.sin_family = PF_INET;
	     their_addr.sin_port = htons(myport);
	     their_addr.sin_addr.s_addr =  inet_addr("10.3.52.16");  //all ip address can be clients
		 bzero(&(their_addr.sin_zero),0);
         //========================================================

	      if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr)) == -1)
	     {
	         perror("bind is error\n");
	         exit(1);
	     }

	     if(listen(sockfd,listnum) == -1)
	     {
	         perror("listen is error\n");
	         exit(1);
	     }
	     printf("start to listen for the main board\n");


	     while(1)
	     {
	         sin_size = sizeof(struct sockaddr_in);

	         if((new_fd = accept(sockfd,(struct sockaddr *)&their_addr,&sin_size)) == -1)
	         {
	             perror("accept is error\n");
	             continue;

	         }
	         printf("Child Board server to send recognized number: \n got connection from Main Board %s\n",inet_ntoa(their_addr.sin_addr));
	         int connected= 1;


	                 char *p;
	                 char sock_buf[1024];
	                 bzero(sock_buf, 1024);
	                 p = sock_buf;

			 char recognized_number[2];
			 while(connected)
			 {
				 if(flag_received_segment)
				 {
					 recognized_number[0]= '0'+ num1;
					 if(send(new_fd, &recognized_number[0],14, 0) == -1)
					 {
						 perror("send is error\n");
						 close(new_fd);
						 exit(0);
					 }
					 flag_received_segment= 0;
					 printf("sent number from child board is:%d\n", num1);
				 }
				 usleep(100000); //wait for 0.1s
			 }
	     }

  }
 void ReceiveSegment(unsigned char* s)
 {
	    //Receive numbers from child boards: TCP protocal as client
	 	int sockfd;
	 	char buffer[1024];
	 	struct sockaddr_in server_addr;
	 	struct hostent *host;
	 	int portnumber,nbytes;
		int result;
		char result_char;

	 	if((host=gethostbyname("10.3.52.16"))==NULL)
	 	{
	 	printf("Gethostname error\n");
	 	//exit(1);
	 	}

	 	if((portnumber=atoi("2013"))<0)
	 	{
	 	printf("Port number error\n");
	 	//exit(1);
	 	}
	 	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	 	{
	 	printf("Socket Error:%s\a\n",strerror(errno));
	 	//exit(1);
	 	}
	 	bzero(&server_addr,sizeof(server_addr));
	 	server_addr.sin_family=AF_INET;
	 	server_addr.sin_port=htons(portnumber);
	 	server_addr.sin_addr=*((struct in_addr *)host->h_addr);
	 	if(connect(sockfd,(struct sockaddr *)(&server_addr),
	 	sizeof(struct sockaddr))==-1)
	 	{
	 	printf("Connect Error:%s\a\n",strerror(errno));
	 	exit(1);
	 	}

	 	while(1)
	 	{
	 		if((nbytes=read(sockfd,buffer,MAXSIZE))==-1)
	 		{
	 		printf("Read Error:%s\n",strerror(errno));
	 		exit(1);
	 		}
	 		buffer[nbytes]='\0';
			
			/* recognition of the segment using SVM */
			//extract features from standards
		    result= SVM_Recognition(buffer);
			result_char = result + '0';
			
	 		printf("I have received segment, recognized as:%s\n", result_char);
            flag_received_segment= 1;
	 		//Send recognized number to main thread by named pipes
	 		num1= result;
	 	}
	 	 close(sockfd);
 }

 int main(void)
{
	//-----------------------------------------------------------------------//
	printf("----------------------------------------------------------------\n");
	printf("---------Plate segmentation and recognition---------------------\n");
	printf("-----------------Child Board 1 Program--------------------------\n");
	printf("----------------------------------------------------------------\n");
	printf("\n\n\n\n\n\n\n");
   //------------------------Declaration of variables--------------------------//
   int check;//, flag= -1;
   //seg threads receive plate segments from the main board(as client)
   pthread_t     seg1_thread;
   pthread_t     seg2_thread;
   pthread_t     seg3_thread;
   pthread_t     seg4_thread;
   //num threads send recognized numbers to the main board(as server)
   pthread_t     num1_thread;
   pthread_t     num2_thread;
   pthread_t     num3_thread;
   pthread_t     num4_thread;

   num1=1; num2=2; num3=3; num4= 4;
   unsigned char*  segment1;
   unsigned char*  segment2;
   unsigned char*  segment3;
   unsigned char*  segment4;

   //Create the thread to read images from memory
   check = pthread_create(&seg1_thread, NULL, (void *)&ReceiveSegment, (void *)(segment1));
     if (check!=0)  printf("seg1_thread error\n");
  /* check = pthread_create(&seg2_thread, NULL, (void *)&ReceiveSegment, (void *)(segment2));
     if (check!=0)  printf("seg2_thread error\n");
   check = pthread_create(&seg3_thread, NULL, (void *)&ReceiveSegment, (void *)(segment3));
     if (check!=0)  printf("seg3_thread error\n");

   check = pthread_create(&seg4_thread, NULL, (void *)&ReceiveSegment, (void *)(segment4));
     if (check!=0)  printf("seg4_thread error\n");*/

    check = pthread_create(&num1_thread, NULL, (void *)&SendNumber1, (void *)(&num1));
	  if (check!=0)  printf("num1_thread error\n");
	/*check = pthread_create(&num2_thread, NULL, (void *)&SendNumber2, (void *)(&num2));
	  if (check!=0)  printf("num2_thread error\n");
	check = pthread_create(&num3_thread, NULL, (void *)&SendNumber3, (void *)(&num3));
	  if (check!=0)  printf("num3_thread error\n");
	check = pthread_create(&num4_thread, NULL, (void *)&SendNumber4, (void *)(&num4));
	  if (check!=0)  printf("num4_thread error\n");*/

	  pthread_join(seg1_thread, NULL);
	  pthread_join(num1_thread, NULL);
	 /* pthread_join(num2_thread, NULL);
	  pthread_join(num3_thread, NULL);
	  pthread_join(num4_thread, NULL);*/

   return EXIT_SUCCESS;
}

