/*
 * the thread for the server
 */

#ifdef WINDOWS_OS

#define BUFFER_SIZE 1024

DWORD WINAPI ThreadFunc( LPVOID lpParam ) 
{ 
   	char buffer[BUFFER_SIZE]; // probably don't need this much space...
	char outputBuffer[BUFFER_SIZE];

	string t("HI");
	SmallSocket SS(SmallSocket::SERVER);

    sprintf( outputBuffer, "Server Started", *(DWORD*)lpParam ); 
	
	while (true)
	{
		SS.receive(buffer,BUFFER_SIZE);
		cout << "Received: " << buffer << endl;

		if (strncmp(buffer,"quit",4) == 0)   // we can shut everything down from here
		{
			timeToQuitNow = 1;    // tell the other thread to quit, too!
			printf("Received a shutdown message from the client.\n");
			sprintf(outputBuffer,"quit");
			int message_length = (int)(strlen(outputBuffer));
			SS.sendout(outputBuffer,message_length);
			break; // stop communicating!
		}
		
		else if (strncmp(buffer,"status",6) == 0)   // check on whether the blobs are running...
		{
			printf("Received a status message from the client.\n");
			sprintf(outputBuffer,"Status: blobsAreOn is %d", blobsAreOn);
			int message_length = (int)(strlen(outputBuffer));
			SS.sendout(outputBuffer,message_length);
		}

		else if (strncmp(buffer,"get",3) == 0)   // check on whether the blobs are running...
		{
			int offset, y; // offsets into the outputBuffer string
			printf("Received a blobs message from the client.\n");

			int numColors = 5;
			int numBlobs = 3;
			offset = sprintf_s(outputBuffer, BUFFER_SIZE-1, "%d ", numColors); 

			for (int c = 0 ; c < numColors ; ++c ) // c == colorNumber
			{
				y = sprintf_s(outputBuffer+offset, BUFFER_SIZE-1-offset, "c%d ", c); // indicate the color number
				offset += y;
				if (offset > BUFFER_SIZE-1) 
				{
					printf("offset got too big (%d) in the string to send\n", offset);
					printf("The string was [\n%s\n]\n", outputBuffer);
					c = numColors+1;
					break;
				}

				for (int i=0 ; i<numBlobs ; ++i) // i == blobNumber
				{
					y = sprintf_s(outputBuffer+offset, BUFFER_SIZE-1-offset, "b%d %d %d %d %d ", 
									i, // blob number
									colorData[c].xmin[i],
									colorData[c].xmax[i],
									colorData[c].ymin[i],
									colorData[c].ymax[i]
									/* ,colorData[c].colour */);
					offset += y;
					if (offset > BUFFER_SIZE-1) 
					{
						printf("offset got too big (%d) in the string to send\n", offset);
						printf("The string was [\n%s\n]\n", outputBuffer);
						//i = numBlobs+1;
						c = numColors+1;
						break;
					}
				} // end for (int i=0 ; i<3 (blobNumber)
			} // end for (int c=0 ; c<numColors (colorNumber)

			int message_length = (int)(strlen(outputBuffer));
			SS.sendout(outputBuffer,message_length);
		}

		else if (buffer[0] == 'e') {
			// just an example of passing in more information
			// and using sscanf to extract it
			// sscanf(recvbuf,"q %lf %lf %lf ",&savedXforLog,&savedYforLog,&savedTforLog);
			//
			//the connection requires that something come back...
			// note that we're sending two zeros every time here...
			sprintf(outputBuffer, "%d %d", 42, 2008);
			int message_length = (int)(strlen(outputBuffer));
			SS.sendout(outputBuffer,message_length);
		}

	    /*
		else if (!strncmp("sendingdata",recvbuf,(int)strlen("sendingdata"))) {
			// acknowledge message
			cout << "Got a sendingdata message\n\n";
			// parse it
			char s[30];
			sscanf(recvbuf, "%s %d %d %d %d %d %d", s, &R_Min, &R_Max, &G_Min, &G_Max, &B_Min, &B_Max);
			printf("%s %d %d %d %d %d %d\n", s, R_Min, R_Max, G_Min, G_Max, B_Min, B_Max);
			// always need to reply....
			SS.sendout("hi",3);
		}
		*/

		else {
			// we always need to reply....
			sprintf(outputBuffer, "Message unrecognized: [ %s ]", buffer);
			int message_length = (int)(strlen(outputBuffer));
			SS.sendout(outputBuffer,message_length);
			printf("Message unrecognized: [ %s ]\n", buffer);
		}

		// pause for a bit...
		Sleep(100);
	}

    return 0; 
} 

#endif

#ifdef MAC_OS

/*
 * the server thread
 */
void *runServerThread(void *portid)
{
  int BUFFER_SIZE=1024;                    // maximum network message size
  int DEFAULT_PORT=2000;                   // our port
  char buffer[BUFFER_SIZE];                // the message buffer (input)
  char outputBuffer[BUFFER_SIZE];          // the output buffer
  unsigned int sockfd, newsockfd, clilen;  // network variables
  struct sockaddr_in serv_addr, cli_addr;  // network configuration
  int n;
  
  memset(buffer,0,BUFFER_SIZE);  // clear out the network message buffer
  memset((char *) &serv_addr, 0, sizeof(serv_addr)); // clear serv_addr
  
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0) printf("ERROR opening socket");
  
  serv_addr.sin_family = AF_INET;          // parameters to bind to port
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(DEFAULT_PORT);
  if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
    printf("ERROR on binding");  
  
  printf("Server listening on port %d.\n", DEFAULT_PORT);
  listen(sockfd,1);          // no need to wait for more than 1 connection!
  clilen = sizeof(cli_addr); // needed for the call to accept
  
  /*
   * this loop allows it to connect to clients repeatedly via the call to accept
   */
  while (!timeToQuitNow) // in case the main thread shuts the server down
  {
    
    /*
     * this next call (to accept) blocks
     */
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    printf("Server accepted a connection... .\n");
    
    if (newsockfd < 0) printf("ERROR on accept");
    
    /*
     * conversation with this client...
     */
    while (!timeToQuitNow) // in case the main thread shuts the server down
    {
      /*
       * read in the message
       */
      n = read(newsockfd,buffer,BUFFER_SIZE-1); // trailing zero
      if (n < 0) 
      {
        printf("Error reading from socket, n = %d\n", n);
        break;
      }
      buffer[n]=0;
      printf("The server received the message: %s\n",buffer);
      
      if (strncmp(buffer,"quit",4) == 0)   // we can shut everything down from here
      {
        timeToQuitNow = 1;    // tell the other thread to quit, too!
        printf("Received a shutdown message from the client.\n");
        snprintf(outputBuffer,BUFFER_SIZE-1,"quit");
        n = write(newsockfd, outputBuffer, strlen(outputBuffer));
      }
      
      else if (strncmp(buffer,"A ",2) == 0)   // looking for an "A " message
      {
        sscanf(buffer, "A %d", &runAlgorithm);
        printf("Setting runAlgorithm to %d.\n", runAlgorithm);
        snprintf(outputBuffer,BUFFER_SIZE-1,"%s",buffer); // send the message back
        n = write(newsockfd, outputBuffer, strlen(outputBuffer));
      }
      
      /*
      else if (strncmp(buffer,"R",1) == 0)   // looking for an "Robot" message
      {
        //sscanf(buffer, "R %d", &runAlgorithm);
        //printf("Setting runAlgorithm to %d.\n", runAlgorithm);
        snprintf(outputBuffer,BUFFER_SIZE-1,"%f",averageTargetX); // send the value back
        n = write(newsockfd, outputBuffer, strlen(outputBuffer));
      }
       */
      
      else // unrecognized message from client -> sent back with "unknown message"
      {
        snprintf(outputBuffer,BUFFER_SIZE-1,"unknown message -> %s",buffer);
        n = write(newsockfd, outputBuffer, strlen(outputBuffer));
      }
      
      if (n < 0) 
      {
        printf("Error writing to socket, n = %d\n", n);
        break;
      }
      
      // clear out old data from the buffer... 
      memset(buffer, 0, n);  // there were n bytes written last time...
    }
    printf("Lost that client connection.\n");
    if (timeToQuitNow) break;  // is it time to quit?
                               // if not, we wait for another connection ...
  }
  
  printf("Server thread quitting.\n");
  pthread_exit(NULL);   // allows other threads to continue running...
}



#endif 

