// Sock srv repeat
#include <stdio.h> //printf(), fprintf(), perror()
#include <sys/socket.h> //socket(), bind(), accept(), listen()
#include <arpa/inet.h> // struct sockaddr_in, struct sockaddr, inet_ntoa()
#include <stdlib.h> //atoi(), exit(), EXIT_FAILURE, EXIT_SUCCESS
#include <string.h> //memset()
#include <unistd.h> //close()

#include "../../../config.h"

#define QUEUELIMIT 5
#define MSGSIZE 32768
#define BUFSIZE (MSGSIZE + 1)

int clitSock;

/*---------------------- internal function ---------------*/
//Remove White Space from string
void rmwhsp(char* text){
  int i,slen;
  slen=strlen(text);

  for (i=1;i<slen;i++){
    if(*(text+i)==' '){
       *(text+i)='\0';
      return;	
    }
  }
  *(text+slen)='\0';
}

void getswcparam(char *name,char *val){
  char nm[1024];
  char vl[1024];
  int slen;
  
  strcpy(nm,name);
  slen=strlen(nm);
  swcget_(nm,vl,slen,1024);
  rmwhsp(vl);
  strcpy(val,vl);
  
}

void getglcparam(char *name,char *val){
  char nm[1024];
  char vl[1024];
  int slen;
  
  strcpy(nm,name);
  slen=strlen(nm);
  glcget_(nm,vl,slen,1024);
  rmwhsp(vl);
  strcpy(val,vl);
  
}

void getgliparam(char *name,int *val){
  char nm[1024];
  int slen;
  
  strcpy(nm,name);
  slen=strlen(nm);

  strcpy(nm,name);
  gliget_(nm,val,slen);
  
}


int recvint(int *idat){
  int data;
  int recvMsgSize;
  if ((recvMsgSize = recv(clitSock, &data, sizeof(int), 0)) < 0) {
    perror("recv() failed.");
    exit(EXIT_FAILURE);
  }else if(recvMsgSize == 0){
    fprintf(stderr, "connection closed by foreign host.\n");
    exit(1);
  }else{
    *idat=ntohl(data); 
  }
}

int recviary(int* img,int nlen){
  int image[8192];
  int i;
  int recvMsgSize;
   
  if ((recvMsgSize = recv(clitSock,(void *) image, nlen*sizeof(int), 0)) < 0) {
    perror("recv() failed.");
    exit(EXIT_FAILURE);
  }else if(recvMsgSize == 0){
    fprintf(stderr, "connection closed by foreign host.\n");
    exit(1);
  }else{
    //    snprintf(rmsg,recvMsgSize,"%s\0",recvBuffer); 
    for(i=0;i<nlen;i++){
      *(img+i)=ntohl(image[i]);
    }
  }
}

int recvstr(char* buff,int dlen){
  int recvMsgSize;
  
  if ((recvMsgSize = recv(clitSock, buff, dlen, 0)) < 0) {
    perror("recv() failed.");
    exit(EXIT_FAILURE);
  }else if(recvMsgSize == 0){
    fprintf(stderr, "connection closed by foreign host.\n");
    exit(1);
  }else{
    //    snprintf(rmsg,recvMsgSize,"%s\0",recvBuffer);
    *(buff+dlen)='\0';
  }
}

int recvrnum(float* fdat){
  char fdatbuff[80];
  int  fstrlen;
  double ddat;
  recvint(&fstrlen);
  recvstr(fdatbuff,fstrlen);
  ddat=atof(fdatbuff);
  *fdat=(float) ddat;
}

int sendinum(DCL_INT data){
  //	     int server, DCL_INT data) {
  int sdata;  
  sdata=htonl((int) data);
  if (send(clitSock, &sdata, sizeof(int), 0) <= 0) {
        perror("send() failed.");
        exit(EXIT_FAILURE);
    }
}

int senddata(const char* data,int size){
  sendinum((DCL_INT) size);
  if (send(clitSock, data, size, 0) <= 0) {
    perror("send() failed.");
    exit(EXIT_FAILURE);
  }
}

int sendrnum(float num){
  char number[17];
  sprintf(number,"%f ",num);
  senddata(number,strlen(number));
}


void sckdopn(){
  int slen;
  DCL_INT dev_type;
  DCL_INT width;
  DCL_INT height;
  DCL_INT iposx;
  DCL_INT iposy;
  DCL_INT idmpdgt;
  DCL_INT ibgpage;
  DCL_REAL rlwfact;
  DCL_INT lwait;
  DCL_INT lwait0;
  DCL_INT lwait1;
  DCL_INT lalt;
  DCL_INT lstdot;
  DCL_INT lkey;
  DCL_INT ldump;
  DCL_INT lwnd;
  DCL_INT lfgbg;
  DCL_INT lsep;
  DCL_INT ifln;
  char cimgfmt[8];
  DCL_REAL rimgcmp;
  char clrmap[2048],cbmmap[2048],file[2048],title[2048];
  char dspath[2048],clrmapfname[2048],cbmmapfname[2048];
  char *adr;

  char text[1024];
  int  ipar;
  
  getglcparam("DSPATH",dspath);
  getswcparam("CLRMAP",clrmapfname);
  getswcparam("BITMAP",cbmmapfname);

  recvint(&dev_type);
  recvint(&width);
  recvint(&height);
  recvint(&iposx);
  recvint(&iposy);
  recvint(&idmpdgt);
  recvint(&ibgpage);
  recvrnum(&rlwfact);
  recvint(&lwait);
  recvint(&lwait0);
  recvint(&lwait1);
  recvint(&lalt);
  recvint(&lstdot);
  recvint(&lkey);
  recvint(&ldump);
  recvint(&lwnd);
  recvint(&lfgbg);
  recvint(&lsep);
  recvint(&ifln);
  recvint(&slen);
  recvstr(cimgfmt,slen);
  recvrnum(&rimgcmp);
  recvint(&slen);
  recvstr(clrmap,slen);
  recvint(&slen);
  recvstr(cbmmap,slen);
  recvint(&slen);
  recvstr(file,slen);
  recvint(&slen);
  recvstr(title,slen);

  adr = strstr(clrmap,clrmapfname);
  strcpy(clrmap,dspath);
  strcat(clrmap,adr);
  adr = strstr(cbmmap,cbmmapfname);
  strcpy(cbmmap,dspath);
  strcat(cbmmap,adr);

  zgdopn_(&dev_type, &width, &height, &iposx, &iposy,
	  &idmpdgt, &ibgpage, &rlwfact,
          &lwait, &lwait0, &lwait1, &lalt , &lstdot,
          &lkey, &ldump, &lwnd, &lfgbg, &lsep, &ifln,
          cimgfmt, &rimgcmp, clrmap, cbmmap, file, title
          );
}

void scklset(){
  char pmname[2048];
  int pl;
  DCL_INT value;

  recvint(&pl);
  recvstr(pmname,pl);
  recvint(&value);  
  zglset_(pmname, &pl, &value);
}
	    
void sckiset(){
  int slen;
  char pmname[2048];
  int pl;
  DCL_INT value;

  recvint(&pl);
  recvstr(pmname,pl);
  recvint(&value);

  zgiset_(pmname, &pl, &value);
}

void sckrset(){
  int slen;
  char pmname[2048];
  int pl;
  DCL_REAL value;

  recvint(&pl);
  recvstr(pmname,pl);
  recvint(&value);

  zgrset_( pmname, &pl, &value);
}

void sckfint(){
  DCL_REAL wx;
  DCL_REAL wy;
  DCL_INT iwx;
  DCL_INT iwy;

  recvrnum(&wx);
  recvrnum(&wy);

  zgfint_(&wx,&wy,&iwx,&iwy);

  sendinum(iwx);
  sendinum(iwy);
}

void sckfrel(){
  DCL_REAL wx;
  DCL_REAL wy;
  DCL_REAL rwx;
  DCL_REAL rwy;

  
  recvrnum(&wx);
  recvrnum(&wy);

  zgfrel_(&wx,&wy,&rwx,&rwy);

  sendrnum(rwx);
  sendrnum(rwy);
}

void sckiint(){
  DCL_INT iwx;
  DCL_INT iwy;
  DCL_REAL wx;
  DCL_REAL wy;
  float    fdat;
  
  recvint(&iwx);
  recvint(&iwy);

  zgiint_(&iwx,&iwy,&wx,&wy);

  sendrnum(wx);
  sendrnum(wy);

}

void sckqdrw(){
  //  zgqdrw_();
}
	    
void sckdcls(){
  zgdcls_();
}

void sckpopn(){
  zgpopn_();
}

void sckpcls(){
  zgpcls_();
}

void sckflash(){
  zgflash_();
}

void sckoopn(){
  int slen;
  char objname[2048];
  char comment[2048];

  recvint(&slen);
  recvstr(objname,slen);
  objname[slen]='\0';
  recvint(&slen);
  recvstr(comment,slen);
  comment[slen]='\0';
  
  zgoopn_( objname, comment);
}

void sckocls(){
  int slen;
  char objname[2048];

  recvint(&slen);
  recvstr(objname,slen);
  objname[slen]='\0';
  
  zgocls_( objname);
}

void sckswdi(){
  DCL_INT iwdidx;

  recvint(&iwdidx);

  zgswdi_( &iwdidx);
}

void sckscli(){
  DCL_INT iclidx;

  recvint(&iclidx);

  zgscli_( &iclidx);
}

void sckgopn(void){
  zggopn_();
}

void sckgmov(){
  DCL_REAL wx;
  DCL_REAL wy;

  recvrnum(&wx);
  recvrnum(&wy);

  zggmov_( &wx, &wy);
}

void sckqtxw(){

  char text[2048];
  DCL_INT len;
  DCL_REAL wxch;
  DCL_REAL wych;

  zgqtxw_( &text, &len, &wxch, &wych);
  
  senddata(text,strlen(text));
  sendinum(len);
  sendrnum(wxch);
  sendrnum(wych);

}

void sckclip(){
  DCL_REAL xmin;
  DCL_REAL xmax;
  DCL_REAL ymin;
  DCL_REAL ymax;

  recvrnum(&xmin);
  recvrnum(&xmax);
  recvrnum(&ymin);
  recvrnum(&ymax);

  zgqtxw_( &xmin, &xmax, &ymin, &ymax);
}

void sckrclp(){
  zgrclp_();
}

void scktxt(){
  int slen;
  DCL_REAL wx;
  DCL_REAL wy;
  DCL_REAL size;
  char text[8096];
  DCL_INT len;
  DCL_REAL irota;
  DCL_INT icentz;  

  recvrnum(&wx);
  recvrnum(&wy);
  recvrnum(&size);
  recvint(&slen);
  recvstr(text,slen);
  text[slen]='\0';
  recvint(&len);
  recvrnum(&irota);
  recvint(&icentz);

  zgtxt_( &wx, &wy, &size, text, &len, &irota, &icentz);
}

void sckselectfont(){
  int slen;
  char selected_font[4096];
 
  zgselectfont_( selected_font);
  senddata(selected_font,strlen(selected_font));
}  
 

void sckftfc(){
  int slen;
  char family[4096];

  recvint(&slen);
  recvstr(family,slen);
  family[slen]='\0';
  
  zgftfc_( family);
}
	      

void scksfw(){
  DCL_INT weight;

  recvint(&weight);

  zgsfw_( &weight);
}

void scknumfonts(){
  DCL_INT fntnum;

  recvint(&fntnum);

  zgnumfonts_( &fntnum);
}

void scklistfonts(){
  zglistfonts_();
}

void sckfontname(){
  int slen;
  DCL_INT n;
  char string[4096];
  DCL_INT nmax;

  recvint(&n);
  recvint(&slen);
  recvstr(string,slen);
  string[slen]='\0';
  recvrnum(&nmax);

  zgfontname_( &n, string, &nmax);

}
	    

void sckgplt(){

  DCL_REAL wx;
  DCL_REAL wy;

  recvrnum(&wx);
  recvrnum(&wy);

  zggplt_( &wx, &wy);

}

void sckgcls(void){

  zggcls_();

}

void sckgton(){
  DCL_INT np;
  DCL_REAL wpx[2048];
  DCL_REAL wpy[2048];
  DCL_INT itpat;
  int i;
  
  recvint(&np);

  for(i=0;i<np;i++){
    recvrnum(&wpx[i]);
  }
  for(i=0;i<np;i++){
    recvrnum(&wpy[i]);
  }
  recvint(&itpat);

  zggton_(&np,&wpx,&wpy,&itpat);

}

void sckiopn(){
  DCL_INT iwx;
  DCL_INT iwy;
  DCL_INT iwidth;
  DCL_INT iheight;

  recvint(&iwx);
  recvint(&iwy);
  recvint(&iwidth);
  recvint(&iheight);
  
  zgiopn_( &iwx, &iwy, &iwidth, &iheight);

}

void sckidat(){
  DCL_INT image[8192];
  DCL_INT nlen;
  int i;
  
  recvint(&nlen);
  recviary(image,nlen);
  
  zgidat_( image, &nlen);

}

void sckicls(void){

  zgicls_();

}

void sckqpnt(){
  DCL_REAL wx;
  DCL_REAL wy;
  DCL_INT mb;

  zgqpnt_( &wx, &wy, &mb);

  sendrnum(wx);
  sendrnum(wy);
  sendinum(mb);

}

void sckqwdc(){
  DCL_INT lwdatr;

  zgqwdc_( &lwdatr);
  sendinum(lwdatr);
}

void sckqclc(){
  DCL_INT lclatr;
  
  zgqclc_( &lclatr);

  sendinum(lclatr);


}
	    

void sckqtnc(){
  DCL_INT ltnatr;

  zgqtnc_( &ltnatr);
  sendinum(ltnatr);

  

}

void sckqimc(){
  DCL_INT limatr;

  zgqimc_( &limatr);
  sendinum(limatr);

}

void sckqptc(){
  DCL_INT lptatr;

  zgqptc_( &lptatr);
  sendinum(lptatr);


}

void sckqrct(){
  DCL_REAL wsxmn;
  DCL_REAL wsxmx;
  DCL_REAL wsymn;
  DCL_REAL wsymx;
  DCL_REAL fact;

  zgqrct_( &wsxmn, &wsxmx, &wsymn, &wsymx, &fact);

  sendrnum(wsxmn);
  sendrnum(wsxmx);
  sendrnum(wsymn);
  sendrnum(wsymx);
  sendrnum(fact);

}

void scksrot(){
  DCL_INT iwtrot;

  recvint(&iwtrot);

  zgsrot_( &iwtrot);

}

void scksfcm(){
  DCL_INT lfc;

  recvint(&lfc);

  zgsfcm_( &lfc);

}

void sckslcl(){
  DCL_INT icolor;
  recvint(&icolor);

  zgslcl_( &icolor);

}

void sckstcl(){
  DCL_INT icolor;
  recvint(&icolor);

  zgstcl_( &icolor);

}

void sckiclr(){
  DCL_INT image[8192];
  int nlen;

  recvint(&nlen);
  recviary(image,nlen);

  zgiclr_( image, &nlen);

}

void sckclini(){
  int slen;
  char clrmap[2048];
  DCL_INT lfgbg;

  recvint(&slen);
  recvstr(clrmap,slen);
  recvint(&lfgbg);

  zgclini_( clrmap, &lfgbg);
}

int main(int argc, char* argv[]) {

    int servSock; //server socket descripter
    struct sockaddr_in servSockAddr; //server internet socket address
    struct sockaddr_in clitSockAddr; //client internet socket address
    unsigned short servPort; //server port number
    unsigned int clitLen; // client internet socket address length
    char recvBuffer[BUFSIZE];//receive temporary buffer
    int sendMsgSize; // recieve and send buffer size

    int idata;
    float fdata;
    double ddata;
    
    char rmsg[8192];
    //    char surl[1024];
    int  sprt;
    
    //    getglcparam("SCKURL",surl);
    getgliparam("SCKPORT",&sprt);
    
    if ((servPort = (unsigned short) sprt) == 0) {
        fprintf(stderr, "invalid port number.\n");
        exit(EXIT_FAILURE);
    }

    if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ){
        perror("socket() failed.");
        exit(EXIT_FAILURE);
    }

    
    memset(&servSockAddr, 0, sizeof(servSockAddr));
    servSockAddr.sin_family      = AF_INET;
    servSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servSockAddr.sin_port        = htons(servPort);

    if (bind(servSock, (struct sockaddr *) &servSockAddr, sizeof(servSockAddr) ) < 0 ) {
        perror("bind() failed.");
        exit(EXIT_FAILURE);
    }

    if (listen(servSock, QUEUELIMIT) < 0) {
        perror("listen() failed.");
        exit(EXIT_FAILURE);
    }

    while(1) {
        clitLen = sizeof(clitSockAddr);
        if ((clitSock = accept(servSock, (struct sockaddr *) &clitSockAddr, &clitLen)) < 0) {
            perror("accept() failed.");
            exit(EXIT_FAILURE);
        }
        printf("connected from %s.\n", inet_ntoa(clitSockAddr.sin_addr));

        while(1) {
          recvint(&idata);
	  recvstr(recvBuffer,idata);
          if(strcmp(recvBuffer,"ZGDOPN ")==0){
              sckdopn();
          }else if(strcmp(recvBuffer,"ZGLSET ")==0){
	      scklset();
	  }else if(strcmp(recvBuffer,"ZGISET ")==0){
	      sckiset();
	  }else if(strcmp(recvBuffer,"ZGRSET ")==0){
	      sckrset();
          }else if(strcmp(recvBuffer,"ZGFINT ")==0){
	      sckfint();
          }else if(strcmp(recvBuffer,"ZGFREL ")==0){
	      sckfrel();
          }else if(strcmp(recvBuffer,"ZGIINT ")==0){
	      sckiint();
          }else if(strcmp(recvBuffer,"ZGQDRW ")==0){
	      sckqdrw();
	  }else if(strcmp(recvBuffer,"ZGDCLS ")==0){
	      sckdcls();
          }else if(strcmp(recvBuffer,"ZGPOPN ")==0){
	      sckpopn();
          }else if(strcmp(recvBuffer,"ZGPCLS ")==0){
	      sckpcls();
          }else if(strcmp(recvBuffer,"ZGFLASH ")==0){
	      sckflash();
          }else if(strcmp(recvBuffer,"ZGOOPN ")==0){
	      sckoopn();
          }else if(strcmp(recvBuffer,"ZGOCLS ")==0){
	      sckocls();
          }else if(strcmp(recvBuffer,"ZGSWDI ")==0){
	      sckswdi();
          }else if(strcmp(recvBuffer,"ZGSCLI ")==0){
	      sckscli();
          }else if(strcmp(recvBuffer,"ZGGOPN ")==0){
	      sckgopn();
          }else if(strcmp(recvBuffer,"ZGGMOV ")==0){
	      sckgmov();
          }else if(strcmp(recvBuffer,"ZGQTXW ")==0){
	      sckqtxw();
          }else if(strcmp(recvBuffer,"ZGCLIP ")==0){
	      sckclip();
	  }else if(strcmp(recvBuffer,"ZGRCLP ")==0){
	      sckrclp();
          }else if(strcmp(recvBuffer,"ZGTXT ")==0){
	      scktxt();
          }else if(strcmp(recvBuffer,"ZGSELECTFONT ")==0){
	      sckselectfont();
          }else if(strcmp(recvBuffer,"ZGFTFC ")==0){
	      sckftfc();
          }else if(strcmp(recvBuffer,"ZGSFW ")==0){
	      scksfw();
          }else if(strcmp(recvBuffer,"ZGNUMFONTS ")==0){
	      scknumfonts();
          }else if(strcmp(recvBuffer,"ZGLISTFONTS ")==0){
	      scklistfonts();
          }else if(strcmp(recvBuffer,"ZGFONTNAME ")==0){
	      sckfontname();
          }else if(strcmp(recvBuffer,"ZGGPLT ")==0){
	      sckgplt();
          }else if(strcmp(recvBuffer,"ZGGCLS ")==0){
	      sckgcls();
          }else if(strcmp(recvBuffer,"ZGGTON ")==0){
	      sckgton();
          }else if(strcmp(recvBuffer,"ZGIOPN ")==0){
	      sckiopn();
          }else if(strcmp(recvBuffer,"ZGIDAT ")==0){
	      sckidat();
          }else if(strcmp(recvBuffer,"ZGICLS ")==0){
	      sckicls();
          }else if(strcmp(recvBuffer,"ZGQPNT ")==0){
	      sckqpnt();
          }else if(strcmp(recvBuffer,"ZGQWDC ")==0){
	      sckqwdc();
          }else if(strcmp(recvBuffer,"ZGQCLC ")==0){
	      sckqclc();
          }else if(strcmp(recvBuffer,"ZGQTNC ")==0){
	      sckqtnc();
          }else if(strcmp(recvBuffer,"ZGQIMC ")==0){
	      sckqimc();
          }else if(strcmp(recvBuffer,"ZGQPTC ")==0){
	      sckqptc();
          }else if(strcmp(recvBuffer,"ZGQRCT ")==0){
	      sckqrct();
          }else if(strcmp(recvBuffer,"ZGSROT ")==0){
	      scksrot();
          }else if(strcmp(recvBuffer,"ZGSFCM ")==0){
	      scksfcm();
          }else if(strcmp(recvBuffer,"ZGSLCL ")==0){
	      sckslcl();
          }else if(strcmp(recvBuffer,"ZGSTCL ")==0){
	      sckstcl();
          }else if(strcmp(recvBuffer,"ZGICLR ")==0){
	      sckiclr();
          }else if(strcmp(recvBuffer,"ZGCLINI ")==0){
	      sckclini();
	  }else{
	      printf("Undefined Function!",recvBuffer);    
	  }	      
	}
        printf("Out of While\n");
        close(clitSock);

    }

    close(servSock);

    return EXIT_SUCCESS;
	    }

