#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef __APPLE__
#  ifdef _WIN32
#    include <windows.h>
#  endif
#  include <GL/glut.h>
#else
#  include <GLUT/glut.h>
#endif
#include <AR/ar.h>
#include <AR/gsub.h>
#include <AR/video.h>
#include <AR/arMulti.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>


#define                 CPARA_NAME       "Data/camera_para.dat"
#define                 CONFIG_NAME      "Data/multi/marker.dat"
#define									max_produit				51

ARHandle               *arHandle;
AR3DHandle             *ar3DHandle;
ARGViewportHandle      *vp;
ARMultiMarkerInfoT     *config;
int                     robustFlag = 0;
int                     count;
int 										t1[max_produit];
int 										t2[max_produit];
int 										t3[max_produit];
int 										t4[max_produit];
int 										t5[max_produit];
int 										t6[max_produit];
ARParamLT              *gCparamLT = NULL;
double         		      patt_width = 40.0;

char									 *tab1="30049e65ccae7200";
char									 *tab2="3004a65dd1ae7200";
char									 *tab3="30049e9d92db7200";      
char									 *tab4="3004a255d4ae7200";     
char									 *tab5="300446e4e51e8200";   
char									 *tab6="30049553c2ae7200";
char 									 * cip;

static void             init(int argc, char *argv[]);
static void             cleanup(void);
static void             mainLoop(void);
static void             keyEvent( unsigned char key, int x, int y);

struct arg_struct {
    char *tab;
    char *ip;
    int prod;
}args;

int main(int argc, char *argv[])
{
  int sock = socket(PF_INET, SOCK_STREAM,0);
  if(sock == -1) {
    perror("main: socket \n" );
    exit(1);
  }
	u_int32_t nip;
	getMyIP(sock,"eth0",&nip);
	struct in_addr in;
	in.s_addr = nip;
	cip =  inet_ntoa( in );
	args.ip=cip;
	//printf("my IP: %s\n",cip);

	glutInit(&argc, argv);
    init(argc, argv);

    argSetDispFunc( mainLoop, 1 );
    argSetKeyFunc( keyEvent );	
    count = 0;
    arVideoCapStart();
    arUtilTimerReset();
    argMainLoop();
	return (0);
}

int getMyIP(int fd, char* ifname,  u_int32_t * ipaddr) {
  /* fd: opened file descriptor
   * ifname: if name eg: "eth0"
   */
#define	IFNAMSIZ 16
struct ifreq
{
    char	ifr_name[IFNAMSIZ];
    struct	sockaddr ifr_addr;
};
  struct ifreq ifr;
  memcpy(ifr.ifr_name,ifname,IFNAMSIZ);
  if(ioctl(fd,SIOCGIFADDR,&ifr) == -1){
    perror("getMyIP: ioctl" );
    exit(-1);
}
  memcpy(ipaddr,&ifr.ifr_addr.sa_data[2],4);
  return 0;
}

static void   keyEvent( unsigned char key, int x, int y)
{
    int     debug;
    int     thresh;

    /* quit if the ESC key is pressed */
    if( key == 0x1b ) {
        ARLOG("*** %f (frame/sec)\n", (double)count/arUtilTimer());
        cleanup();
        exit(0);
    }

    if( key == 'd' ) {
        arGetDebugMode( arHandle, &debug );
        debug = 1 - debug;
        arSetDebugMode( arHandle, debug );
    }

    if( key == '1' ) {
        arGetDebugMode( arHandle, &debug );
        if( debug ) {
            arGetLabelingThresh( arHandle, &thresh );
            thresh -= 5;
            if( thresh < 0 ) thresh = 0;
            arSetLabelingThresh( arHandle, thresh );
            ARLOG("thresh = %d\n", thresh);
        }
    }
    if( key == '2' ) {
        arGetDebugMode( arHandle, &debug );
        if( debug ) {
            arGetLabelingThresh( arHandle, &thresh );
            thresh += 5;
            if( thresh > 255 ) thresh = 255;
            arSetLabelingThresh( arHandle, thresh );
            ARLOG("thresh = %d\n", thresh);
        }
    }

    if( key == ' ' ) {
        robustFlag = 1 - robustFlag;
        if( robustFlag ) ARLOG("Robust estimation mode.\n");
        else             ARLOG("Normal estimation mode.\n");
    }
}

void *my_thread_process (void * arg)
{/*
  int i;
  for (i = 0 ; i < 1 ; i++) {
    printf ("Thread %s: %d\n", (char*)arg, i);
sleep(1);
  }
  */

  int status,prod;
  char *tab;
  char *ip;
  char www[80];
  pid_t pid;

  pid = fork ();
  if (pid == 0)
    {
          /* This is the child process.  Execute the command. */
    tab=args.tab;
    prod=args.prod;
    //printf("%s\n",args.ip);
    ip=args.ip;
    sprintf(www, "http://%s/tab/index.php?id=%d", ip, prod);
    //printf("%s\n", www);
    execl("/usr/bin/adb", "adb", "-s", tab, "shell", "am", "start", "-a", "android.intent.action.VIEW", "-d", www, (char *)NULL);
  /*printf("%s\n", tab);
    printf("%d\n", prod);*/
      _exit (EXIT_FAILURE); 	
    }
  else if (pid < 0)
    /* The fork failed.  Report failure.  */
    status = -1;
  else
    /* This is the parent process.  Wait for the child to complete.  */
    if (waitpid (pid, &status, 0) != pid)
      status = -1;
  sleep(10);
  pthread_exit (0);
}

/* main loop */
static void mainLoop(void)
{
    ARUint8         *dataPtr;
    ARMarkerInfo    *marker_info;
    int             marker_num;
    int             imageProcMode;
    int             debugMode;
    double          err;
    int             i,j1,j2,j3,j4,j5,j6;
    static ARdouble patt_trans[3][4];


    /* grab a video frame */
    if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
        arUtilSleep(2);
        return;
    }

    if( count == 100 ) {
        ARLOG("*** %f (frame/sec)\n", (double)count/arUtilTimer());
        arUtilTimerReset();
        count = 0;
    }
    count++;

    /* detect the markers in the video frame */
    if( arDetectMarker(arHandle, dataPtr) < 0 ) {
        cleanup();
        exit(0);
    }
    marker_num = arGetMarkerNum( arHandle );
    marker_info =  arGetMarker( arHandle );

        for( i = 0; i < marker_num; i++ ) {
					if(marker_info[i].id != -1){			
						ARLOG("ID=%d, CF = %f\n", marker_info[i].id, marker_info[i].cf);
						arGetTransMatSquare(ar3DHandle, &(marker_info[i]), patt_width, patt_trans);
						printf("%f %f %f\n",patt_trans[0][3],patt_trans[1][3],patt_trans[2][3]);
						printf("______________________________\n");
						
						if(patt_trans[0][3] < -250 && patt_trans[0][3] < 0 ){
							int pres_tab1=0;
							pthread_t th1;
						
							for( j1=0; j1 < max_produit; j1++){
								//printf("ID : %d  ___  t1 : %d\n", marker_info[i].id, t1[j1]);
								if(marker_info[i].id == t1[j1]) pres_tab1=1;
							}
							//printf("_________________________________\n");
							//printf("pres_tab1 : %d\n",pres_tab1);
							//printf("_________________________________\n");
							if(pres_tab1 != 1){
								t1[marker_info[i].id]=marker_info[i].id;
								args.tab = tab1;
		  					args.prod = marker_info[i].id +1;
								if (pthread_create (&th1, NULL, my_thread_process, (void *)&args) < 0) {
								fprintf (stderr, "pthread_create error for thread 1\n");
								exit (1);}
							}
						}
						if(patt_trans[0][3] < -200 && patt_trans[1][3] < 0){
							int pres_tab2=0;
							pthread_t th1;
						
							for( j2=0; j2 < max_produit; j2++){
								//printf("ID : %d  ___  t2 : %d\n", marker_info[i].id, t2[j2]);
								if(marker_info[i].id == t2[j2]) pres_tab2=1;
							}
							//printf("_________________________________\n");
							//printf("pres_tab2 : %d\n",pres_tab2);
							//printf("_________________________________\n");
							if(pres_tab2 != 1){
								t2[marker_info[i].id]=marker_info[i].id;
								args.tab = tab2;
		  					args.prod = marker_info[i].id +1;
								if (pthread_create (&th1, NULL, my_thread_process, (void *)&args) < 0) {
								fprintf (stderr, "pthread_create error for thread 1\n");
								exit (1);}
							}
						}
						if(patt_trans[0][3] < 250 && patt_trans[0][3] > -200 && patt_trans[1][3] < 0){
							int pres_tab3=0;
							pthread_t th1;
						
							for( j3=0; j3 < max_produit; j3++){
								//printf("ID : %d  ___  t3 : %d\n", marker_info[i].id, t3[j3]);
								if(marker_info[i].id == t3[j3]) pres_tab3=1;
							}
							//printf("_________________________________\n");
							//printf("pres_tab3 : %d\n",pres_tab3);
							//printf("_________________________________\n");
							if(pres_tab3 != 1){
								t3[marker_info[i].id]=marker_info[i].id;
								args.tab = tab3;
		  					args.prod = marker_info[i].id +1;
								if (pthread_create (&th1, NULL, my_thread_process, (void *)&args) < 0) {
								fprintf (stderr, "pthread_create error for thread 1\n");
								exit (1);}
							}
						}
						if(patt_trans[0][3] > 250 && patt_trans[1][3] < 0){
							int pres_tab4=0;
							pthread_t th1;
						
							for( j4=0; j4 < max_produit; j4++){
								//printf("ID : %d  ___  t4 : %d\n", marker_info[i].id, t4[j4]);
								if(marker_info[i].id == t4[j4]) pres_tab4=1;
							}
							//printf("_________________________________\n");
							//printf("pres_tab4 : %d\n",pres_tab4);
							//printf("_________________________________\n");
							if(pres_tab4 != 1){
								t4[marker_info[i].id]=marker_info[i].id;
								args.tab = tab4;
		  					args.prod = marker_info[i].id +1;
								if (pthread_create (&th1, NULL, my_thread_process, (void *)&args) < 0) {
								fprintf (stderr, "pthread_create error for thread 1\n");
								exit (1);}
							}
						}
						if(patt_trans[0][3] > 200 && patt_trans[0][3] > 0){
							int pres_tab5=0;
							pthread_t th1;
						
							for( j5=0; j5 < max_produit; j5++){
								//printf("ID : %d  ___  t5 : %d\n", marker_info[i].id, t5[j5]);
								if(marker_info[i].id == t5[j5]) pres_tab5=1;
							}
							//printf("_________________________________\n");
							//printf("pres_tab5 : %d\n",pres_tab5);
							//printf("_________________________________\n");
							if(pres_tab5 != 1){
								t5[marker_info[i].id]=marker_info[i].id;
								args.tab = tab5;
		  					args.prod = marker_info[i].id +1;
								if (pthread_create (&th1, NULL, my_thread_process, (void *)&args) < 0) {
								fprintf (stderr, "pthread_create error for thread 1\n");
								exit (1);}
							}
						}
						if(patt_trans[0][3] < 200 && patt_trans[0][3] > -250 && patt_trans[1][3] > 0){
							int pres_tab6=0;
							pthread_t th1;
						
							for( j6=0; j6 < max_produit; j6++){
								//printf("ID : %d  ___  t6 : %d\n", marker_info[i].id, t6[j6]);
								if(marker_info[i].id == t6[j6]) pres_tab6=1;
							}
							//printf("_________________________________\n");
							//printf("pres_tab6 : %d\n",pres_tab6);
							//printf("_________________________________\n");
							if(pres_tab6 != 1){
								t6[marker_info[i].id]=marker_info[i].id;
								args.tab = tab6;
		  					args.prod = marker_info[i].id +1;
								if (pthread_create (&th1, NULL, my_thread_process, (void *)&args) < 0) {
								fprintf (stderr, "pthread_create error for thread 1\n");
								exit (1);}
							}
						}
					}
				}

    argDrawMode2D(vp);
    arGetDebugMode( arHandle, &debugMode );
    if( debugMode == 0 ) {
        argDrawImage( dataPtr );
    }
    else {
        arGetImageProcMode(arHandle, &imageProcMode);
        if( imageProcMode == AR_IMAGE_PROC_FRAME_IMAGE ) {
            argDrawImage( arHandle->labelInfo.bwImage );
        }
        else {
            argDrawImageHalf( arHandle->labelInfo.bwImage );
        }
        glColor3f( 1.0f, 0.0f, 0.0f );
        glLineWidth( 2.0f);
        for( i = 0; i < marker_num; i++ ) {
            argDrawSquareByIdealPos( marker_info[i].vertex );
        }
        glLineWidth( 1.0f );
    }

    if( robustFlag ) {
        err = arGetTransMatMultiSquareRobust( ar3DHandle, marker_info, marker_num, config);
    }
    else {
        err = arGetTransMatMultiSquare( ar3DHandle, marker_info, marker_num, config);
    }
    if( config->prevF == 0 ) {
        argSwapBuffers();
        return;
    }
    //ARLOGd("err = %f\n", err);

    argDrawMode3D(vp);
    glClearDepth( 1.0 );
    glClear(GL_DEPTH_BUFFER_BIT);
    /*for( i = 0; i < config->marker_num; i++ ) {
        if( config->marker[i].visible >= 0 ) draw( config->trans, config->marker[i].trans, 0 );
        else                                 draw( config->trans, config->marker[i].trans, 1 );
    }*/

    argSwapBuffers();
}

static void   init(int argc, char *argv[])
{
    ARParam         cparam;
    ARGViewport     viewport;
    ARPattHandle   *arPattHandle;
    char            vconf[512];
    char            configName[512];
    int             xsize, ysize;
    AR_PIXEL_FORMAT pixFormat;
    int             i,j;
    
    for(j=0; j<max_produit; j++){
    	t1[j]=99;
    	t2[j]=99;
    	t3[j]=99;
    	t4[j]=99;
    	t5[j]=99;
    	t6[j]=99;}

    configName[0] = '\0';
    vconf[0] = '\0';
    for( i = 1; i < argc; i++ ) {
        if( strncmp(argv[i], "-config=", 8) == 0 ) {
            strcpy(configName, &argv[i][8]);
        }
        else {
            if( vconf[0] != '\0' ) strcat(vconf, " ");
            strcat(vconf, argv[i]);
        }
    }
    if( configName[0] == '\0' ) strcpy(configName, CONFIG_NAME);

    /* open the video path */
    if( arVideoOpen( vconf ) < 0 ) exit(0);
    /* find the size of the window */
    if( arVideoGetSize(&xsize, &ysize) < 0 ) exit(0);
    ARLOGi("Image size (x,y) = (%d,%d)\n", xsize, ysize);
    if( (pixFormat=arVideoGetPixelFormat()) < 0 ) exit(0);

    /* set the initial camera parameters */
    if( arParamLoad(CPARA_NAME, 1, &cparam) < 0 ) {
        ARLOGe("Camera parameter load error !!\n");
        exit(0);
    }
    arParamChangeSize( &cparam, xsize, ysize, &cparam );
    ARLOG("*** Camera Parameter ***\n");
    arParamDisp( &cparam );
    if ((gCparamLT = arParamLTCreate(&cparam, AR_PARAM_LT_DEFAULT_OFFSET)) == NULL) {
        ARLOGe("Error: arParamLTCreate.\n");
        exit(-1);
    }

    if( (arHandle=arCreateHandle(gCparamLT)) == NULL ) {
        ARLOGe("Error: arCreateHandle.\n");
        exit(0);
    }
    if( arSetPixelFormat(arHandle, pixFormat) < 0 ) {
        ARLOGe("Error: arSetPixelFormat.\n");
        exit(0);
    }

    if( (ar3DHandle=ar3DCreateHandle(&cparam)) == NULL ) {
        ARLOGe("Error: ar3DCreateHandle.\n");
        exit(0);
    }

    if( (arPattHandle=arPattCreateHandle()) == NULL ) {
        ARLOGe("Error: arPattCreateHandle.\n");
        exit(0);
    }
    arPattAttach( arHandle, arPattHandle );

    if( (config = arMultiReadConfigFile(configName, arPattHandle)) == NULL ) {
        ARLOGe("config data load error !!\n");
        exit(0);
    }
    if( config->patt_type == AR_MULTI_PATTERN_DETECTION_MODE_TEMPLATE ) {
        arSetPatternDetectionMode( arHandle, AR_TEMPLATE_MATCHING_COLOR );
    } else if( config->patt_type == AR_MULTI_PATTERN_DETECTION_MODE_MATRIX ) {
        arSetPatternDetectionMode( arHandle, AR_MATRIX_CODE_DETECTION );
    } else { // AR_MULTI_PATTERN_DETECTION_MODE_TEMPLATE_AND_MATRIX
        arSetPatternDetectionMode( arHandle, AR_TEMPLATE_MATCHING_COLOR_AND_MATRIX );
    }

    /* open the graphics window */
    viewport.sx = 0;
    viewport.sy = 0;
    viewport.xsize = xsize;
    viewport.ysize = ysize;
    if( (vp=argCreateViewport(&viewport)) == NULL ) exit(0);
    argViewportSetCparam( vp, &cparam );
    argViewportSetPixFormat( vp, pixFormat );
}

/* cleanup function called when program exits */
static void cleanup(void)
{
    arParamLTFree(&gCparamLT);
    arVideoCapStop();
    arVideoClose();
    argCleanup();
}


