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

#define blockSize 1024

int sock=-1;

void handlerExit(int sig){
  printf("\n---Interruption %i---\n\n",sig);
  close(sock);
  exit(0);
}

void handlerGetOutSon(int sig){
  wait();
}

int existOrNot(char* filename)
{
  int res=-1;
  FILE* pt_file;

  if(pt_file = fopen(filename,"rw+"))
  {
    res=0;
    fclose(pt_file);
  }
  else
  {
    res=1;
  }
  return res;
}

int main(){
  struct trameHttp{
    char request[32];
    char target[64];
    char protocol[16];
  };


  //none are work :'(
  signal(9,handlerExit);
  signal(SIGINT,handlerExit);
  signal(SIGKILL,handlerExit);
  signal(SIGTERM,handlerExit);
  //..
  signal(SIGCHLD,handlerGetOutSon);

  
  char* buffer;
  char* talks;
  
  struct sockaddr_in sockaddr;
  sockaddr.sin_family = AF_INET;
  sockaddr.sin_port=ntohs(2009);
  sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

  int cpt0=0;
	
  for(cpt0=0;cpt0<sizeof(sockaddr.sin_zero);cpt0++){
    sockaddr.sin_zero[cpt0]='\0';
  }
  
  printf("\nConnexion ---> ");
  sock=socket(AF_INET,SOCK_STREAM,0);
  
  if(sock<0)
    perror("Erreur sur la creation de socket!!!");
  else
    printf("OK\n");

  printf("bind() ---> ");
  int dbg0 = bind(sock,(struct sockaddr*)&sockaddr,sizeof(struct sockaddr));
  if(dbg0<0)
    perror("Erreur avec le bind()");
  else
    printf("OK\n");
  
  printf("listen() ---> ");
  int dbg1 = listen(sock,1);
  
  if(dbg1<0)
    perror("Erreur avec le listen()");
  else
    printf("OK\n");

  int i=0;
  for(;;){
    int sizeMax = sizeof(struct sockaddr*);
    int sockfd=accept(sock,(struct sockaddr*)&sockaddr,&sizeMax);
    if(sockfd<0) perror("accept()");

    int pidf;
    pidf=fork();
    if(pidf<0)
      perror("fork()");
    else if(pidf==0){
  
      buffer=malloc(sizeof(char)*498);

      int dbg2=read(sockfd,buffer,498);
      if(dbg2<0) perror("read()");
      //printf("CLIENT::%s\n",buffer);
    
      char *adr0, *adr1, *adr2;
      struct trameHttp tr;
      adr0 = strtok(buffer," ");
      adr1 = strtok(NULL," ");
      adr2 = strtok(NULL," ");
      sprintf(tr.request,"%s",adr0);
      sprintf(tr.target,"%s",adr1);
      sprintf(tr.protocol,"%s",adr2);

      //DBG  
      //printf("BUF=>adr0:%s/adr1:%s/adr2:%s\n",tr.request,tr.target,tr.protocol);
      free(buffer);

     
      printf("Request = %s\n",tr.request);
      printf("Target = %s\n",tr.target);

      FILE* myFile;
      char path[128];
      char defaultIndex[]="index.html";
      char default404[]="404.html";

      sprintf(path,"%s",tr.target);

      if(strcmp(path,"/")==0){
	sprintf(path,"%s",defaultIndex);
      }
      else{
	sprintf(path,"%s",path+1);
      }

      int exist = existOrNot(path);
      int alreadyWrote=-1;

      printf("\nExist (%s)= %i\n",path,exist);

      if(exist==1){ //doesn't exist
	if(strcmp(path,"page")==0){
	  /*Stats page*/
	  char hostN[32];
	  char lHostN[256];
	  char header[]="<html><center><h1>Stats Page</h1></center><hr><center>";
	  char *statPage;
	  struct sockaddr_in sockAd;
	  int lenSockAd=sizeof(sockAd);
	  char sockInfo[1024];

	  time_t t;
	  time(&t);
	  char curTime[32];
	  sprintf(curTime,"%s", ctime(&t));

	  gethostname(hostN,sizeof(hostN));
	  sprintf(lHostN,"<table border=1><tr><td>Server Host Name</td><td>%s</td></tr><tr><td>Time</td><td>%s</td><tr>",hostN,curTime);

	  getsockname(sockfd,(struct sockaddr_in*)&sockAd,&lenSockAd);
	  sprintf(sockInfo,"<tr><td>Sockfd</td><td>%d<td></tr><tr><td>Address</td><td>%p</td></tr><tr><td>IP</td><td>%s</td></tr><tr><td>Port</td><td>%u</td></tr></table></center></html>", sockfd, &sockAd, inet_ntoa(sockAd.sin_addr), ntohs(sockAd.sin_port));

	  statPage=malloc((sizeof(header)+sizeof(lHostN)+sizeof(sockInfo))*(sizeof(char)));
	  sprintf(statPage,"%s%s%s",header,lHostN,sockInfo);

	  if(write(sockfd,statPage,strlen(statPage))<0) perror("IO Error with the stats page");
	  alreadyWrote=1;
	}
	else if(existOrNot(default404)!=0){ //no 404 file
	  char hostNerrorP[32];
	  char *errorPageDef;
	  char pageAppend[]="</html>";
	  gethostname(hostNerrorP,sizeof(hostNerrorP));
	  char no404[]="<html><center><h1>404 : Page not found<h1></center><hr>";

	  //malloc errorPageDef
	  errorPageDef=malloc((sizeof(no404)+sizeof(hostNerrorP)+sizeof(pageAppend))*(sizeof(char)));

	  sprintf(errorPageDef,"%s%s%s",no404,hostNerrorP,pageAppend);
	  if(write(sockfd,errorPageDef,strlen(errorPageDef))<0) perror("IO Error with the 404 default page");
	  alreadyWrote=1;
	}
	else{
	  sprintf(path,"%s",default404);
	}
      }

      if(alreadyWrote<=0){
	myFile=fopen(path,"rb");
	char bufferIOF[1024];
	int len=0;
	
	do{
	  len = fread(bufferIOF,1,1,myFile);
	  if(write(sockfd,bufferIOF,len)<0) perror("IO Error");

	}while(len>0);
      }
      close(sockfd);
      exit(0);
    }
    else{
      close(sockfd);
    }
  }
  
  close(sock);
    
  printf("Connexion ---> Done\n");
    
}

