#include <stdio.h>
#include <stdlib.h>
#include "header.h"

#ifdef WIN32
  #include <winsock.h>
  #include <windows.h>
#else
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #define  closesocket close
#endif

#ifndef SOCKET
  #define SOCKET 		int
#endif

#ifndef SOCKET_ERROR
  #define SOCKET_ERROR  -1
#endif

#define BUFSIZE 1024*1024


/*int reqMsg[BUFSIZE];
char repMsg[100];*/

struct requisicao reqMsg;
struct resposta repMsg;


int main(int argc, char *argv[])
{
   #ifdef WIN32
   WSADATA wsda;			// Structure to store information returned from
   #endif					        // WSAStartup
   
   int ret,i,nPorta,tamAddr,tamBuf;

//   char repMsg[BUFSIZE];

   SOCKET sListen, sClient;
   
   struct sockaddr_in addr, remote_addr;

   // Confere argumentos
   if(argc != 2)
   {
      printf("Servidor [nPorta] \n");
      printf("          nPorta: numero da porta a atender requisicoes\n");
      exit(1);
   }

   // Pega o numero da porta
   nPorta = atoi(argv[1]);

   if(nPorta<0 || nPorta>65535)   // 0 < nPorta < 65563
   {
      printf("Numero de Porta Inválido (%s)\n", argv[1]);
      exit(1);
   }

   //se for Windows carrega a biblioteca WinSockets
   #ifdef WIN32
   WSAStartup(MAKEWORD(1,1), &wsda);
   #endif

   // Cria o socket
   printf("Criando socket \n");
   sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
   

   // Erro?
   if(sListen == SOCKET_ERROR)
   {
      printf("Nao consegui criar o socket\n");
      exit(1);
   }
   printf("Fazendo o Bind na porta %d...", nPorta);

   addr.sin_family = AF_INET;
   addr.sin_port = htons(nPorta);
   addr.sin_addr.s_addr = htonl(INADDR_ANY);          // Qualquer Interface de rede

   ret = bind(sListen, (struct sockaddr *) &addr, sizeof(addr));

   // Erro?
   if(ret == SOCKET_ERROR)
   {
      printf("Nao consegui fazer o bind\n");
      exit(1);
   }

   printf("Definindo fila de espera para o socket\n");

   ret = listen(sListen, 10);        // MailBox 10

   // Erro?
   if(ret == SOCKET_ERROR)
   {
      printf("Nao consegui criar a mailbox do socket\n");
      exit(1);
   }

   printf("Aguardando conexoes (Pressione Ctrl-C para cancelar)...\n");
   
   while (1)
   {

      tamAddr = sizeof(remote_addr);
      sClient = accept(sListen, (struct sockaddr *) &remote_addr, &tamAddr);

      // Erro?
      if(sClient == SOCKET_ERROR)
      {
         printf("Nao consegui aceitar a conexao\n");
         exit(1);
      }

      printf("%s conectado \n",inet_ntoa(remote_addr.sin_addr));

      // recebendo requisicao	   
      ret = recv(sClient,(void*)&reqMsg,sizeof(struct requisicao),0);
/*      printf("Recebidos = %d inteiros\n",BUFSIZE              );
      printf("primeiro = %d  ultimo = %d\n",reqMsg[0], reqMsg[BUFSIZE-1]);*/
      
      switch(reqMsg.op)
      {
          case '+':
              repMsg.resultado = reqMsg.n1 + reqMsg.n2;
              repMsg.erro = OK;
              break;
          case '-':
              repMsg.resultado = reqMsg.n1 - reqMsg.n2;
              repMsg.erro = OK;
              break;
          case '/':
              if (reqMsg.n2 != 0)
              {
                 repMsg.resultado = reqMsg.n1 / reqMsg.n2;
                 repMsg.erro = OK;
              }
              else
                 repMsg.erro = DIV_ZERO;
              break;
          default:
              repMsg.erro = INDISPONIVEL;
      }      
      
      //printf("Recebi a mensagem:%s\n",reqMsg);

      //enviando resposta
      //strcpy(repMsg,"Ok");
      ret = send(sClient,(void*)&repMsg,sizeof(struct resposta),0);
      closesocket(sClient);
   }
   #ifdef WIN32
   WSACleanup();
   #endif
   
   
   return 0;
}
