#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>


#include "globals.h"
#include "sizes.h"
#include "status.h"
#include "netdata.h"
#include "netvariables.h"
#include "key.h"
#include "menu.h"
#include "init.h"


struct sockaddr_in servaddr;
int GameType;
float WorldWidth;
int myShip;
int svrsock;


/*
  Function to connect to the game server.
  This function uses the Server IP and Port to connect using UDP
*/
int ConnectServer()
{
  char senddata;
  int n;
  struct timeval timeout;
  struct GameParametersStruct GameParameters;
  int i, rc;

  InitKeyValues();

  if ((svrsock=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    printf("Socket Error\n");
    exit(1);
  }

  // Set a timeout of 5 seconds for listening
  timeout.tv_sec=5;
  timeout.tv_usec=0;
  setsockopt(svrsock, SOL_SOCKET, SO_RCVTIMEO,
             &timeout, sizeof(struct timeval));

  memset(&servaddr, 0, sizeof(servaddr));

  servaddr.sin_family=AF_INET;
  servaddr.sin_port=htons(ServerPort);

#ifdef CYGWIN
  servaddr.sin_addr.s_addr=inet_addr(ServerIP);
#else
  if (inet_pton(AF_INET, ServerIP, &servaddr.sin_addr) <=0) {
    printf("inet_pton error for %s\n", ServerIP);
    exit(2);
  }
#endif

  /*
    Send out a test packet.  For some reason on some platforms the ServerIP
    value for the first packet is incorrect on the server.  So a test packet is
    sent first.  This seems to correct the problem since every packet after
    this works fine.
  */
  senddata=TEST_PACKET;
  sendto(svrsock, &senddata, 1, 0, (struct sockaddr *)&servaddr,
         sizeof(servaddr));

  // Try to connect to the server and receive the game parameters
  for (i=0; i<3; i++) {
    if (i!=0) {
      printf("Error connecting to server, retrying\n");
    }

    if (sendto(svrsock, &PlayerName, MAX_PLAYERNAME_LENGTH, 0,
               (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
      printf("Write Error in Connect Server\n");
      exit(1);
    }
    if ((n=recvfrom(svrsock, (char *)&GameParameters,
                    sizeof(GameParametersStruct), 0, NULL, NULL)) ==
        sizeof(GameParametersStruct)) {
      break;
    }
  }

  if (n!=sizeof(GameParametersStruct)) {
    printf("Failed to connect to server\n");
    AbortGame();
    return(1);
  }

  // Set game parameters read from the connection
  WorldWidth=GameParameters.WorldWidth;
  myShip=ntohs(GameParameters.PlayerNum);
  MaxShield=ntohl(GameParameters.MaxShield);
  MaxArmor=ntohl(GameParameters.MaxArmor);
  GameType=ntohs(GameParameters.GameType);

  return(0);
}


// Function to tell the server the key presses and releases
void TellServer(char keypress, int on)
{
  char sendvalue;

  sendvalue=keypress;

  if (on) {
    sendvalue+=0x10;
  }
  if (sendto(svrsock, &sendvalue, 1, 0, (struct sockaddr *)&servaddr,
                sizeof(servaddr)) < 0) {
    printf("Write Error in TellServer\n");
    exit(1);
  }
}


// Function to send status of all keys to server
void SendUpdate()
{
  if (sendto(svrsock, &KeyValues, sizeof(KeyValuesStruct), 0,
             (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
    printf("Write Error in SendUpdate\n");
    exit(1);
  }
}
