#include "defs.h"
#include "misc.h"
#include "rules.h"
#include "MsgQ.h"
#include "trans.h"
#include "player.h"
#include "world.h"
#include "move.h"
#include "display.h"
#include "city.h"
#include "net.h"
#include "server.h"
#include "savefile.h"

#include <string.h>

enum { INIT, STARTED };

int distanceBetweenConts = 10;
int contChunkSize = 2;
int numberOfChunksPerCont = 70;

int savedGame;

static int status = INIT;

const int NamesPerPlayer = 10;

char *initCityNames[] = {
  "Ludhiana", "Amritsar", "Tarn Tarn", "Phillaur", "Banga",
  "Nawasher", "Malerkotla", "Ambala", "Chandigarh", "Nahan",
  // next players
  "Delhi", "Gurgaon", "Meerut", "Lucknow", "Jaipur",
  "Agra", "Hyderabad", "Calcutta", "Bombay", "Banaras",
  // next
  "Lahore", "Karachi", "Islamabad", "Sind", "Kabul",
  "Tehran", "Baghdad"
  };

char **cityNames;

Player **players;

TransTable *trans;
WDisplay *display = NULL;

MsgQ *moveQ;

int playerId;
int currTurn;

World *world;

void HandleMessage(MsgQ *q, int recvSock, int info)
{
  if (q->Count() == 0) return;
  if (status == INIT) {
    char *buf;
    *q >> buf;
    if (strcmp(buf, "send_map") == 0) {
      Debug('i', "Got map request\n");
      delete q;
      world->Send();
      MsgQ *cmdQ = new MsgQ;
      cmdQ->AddCmd(GET_PLAYER_INFO);
      SendQ(cmdQ);
    }
    else if (strcmp(buf, "map_start") == 0) {
      Debug('i', "Got map\n");
      world = new World(q);
      MsgQ *cmdQ = new MsgQ;
      cmdQ->AddCmd(GET_PLAYER_INFO);
      SendQ(cmdQ);
    }
    else if (strcmp(buf, "player_info") == 0) {
      InitializeRules();
      Debug('i', "Got player info\n");
      *q >> numPlayers;
      players = new PlayerP[numPlayers];
      for (int i = 0; i < numPlayers; ++i) {
	char *name;
	*q >> name;
	if (strcmp(name, myName) == 0) {
	  playerId = i;
	  cityNames = initCityNames+i*NamesPerPlayer;
	}
	players[i] = new Player(name, i);
      }
      delete q;
      trans = new TransTable(playerId);
      display = new WDisplay(world);
      world->AllocColors(); // get the colors
      display->AllocColors();
      AllocCityColors();
      Debug('i', "Initialized to %d players, myid %d\n", numPlayers,
	    playerId);
      MsgQ *cmdQ = new MsgQ;
      cmdQ->AddCmd(SYNCH);
      SendQ(cmdQ);
    }
    else if (strcmp(buf, "synch") == 0) {
      delete q;
      if (savedGame) {
	status = STARTED;
	display->Update();
	if (currTurn == playerId)
	  players[currTurn]->InitMoveTurn();
	else
	  players[playerId]->InitCityTurn();
      }
      else {
	currTurn = 0;
	if (playerId == 0) {
	  players[0]->Setup();
	  Debug('i', "setup player 0, sending moves\n");
	  MsgQ *q = new MsgQ;
	  players[0]->SendMoves(q);
	  SendQ(q);
	  ++currTurn;
	}
      }
    }
    else if (strcmp(buf, "moves") == 0) {
      Debug('i', "showing moves for %d\n", currTurn);
      players[currTurn]->ShowMoves(q, NULL);
      ++currTurn;
      if (currTurn == playerId) {
	players[currTurn]->Setup();
	MsgQ *q = new MsgQ;
	players[currTurn]->SendMoves(q);
	SendQ(q);
	++currTurn;
      }
      if (currTurn == numPlayers) {
	Debug('i', "initialized players, starting now\n");
	status = STARTED;
	currTurn = 0;
	if (currTurn == playerId)
	  players[currTurn]->InitMoveTurn();
	else
	  players[playerId]->InitCityTurn();
      }
    }
    else
      delete q;
    delete buf;
    return;
  }

  if (currTurn == playerId)
    players[currTurn]->MoveTurnMesg(q);
  else
    players[playerId]->CityTurnMesg(q);
}

void HandleKey(int event, int a, int b, char *ptr)
{
  if (status != STARTED)
    return;
  if (currTurn == playerId)
    players[playerId]->MoveTurnKey(event, a, b, ptr);
  else
    players[playerId]->CityTurnKey(event, a, b, ptr);
}

// initializes civ and returns
void CivInit(int option, char *server)
{
  if (option == RestoreSaveFile) {
    Debug('i', "Restoring saved game\n");
    savedGame = 1;
    ReadSaveFile();
    if (playerId == 0)
      InitServer();
    else {
      ConnectServer(server);
      screen->AddReadNotify(sock, HandleMessage);
      MsgQ *q = new MsgQ;
      q->AddCmd(RECONNECT, playerId);
      *q << myName;
      SendQ(q);
    }
    MsgQ *q = new MsgQ;
    q->AddCmd(SYNCH);
    SendQ(q);
  }
  else {
    Debug('i', "Starting new game\n");
    savedGame = 0;
    if (numPlayers > 0) {
      InitServer();
      playerId = 0;
      world = new World(64, 64, distanceBetweenConts,
			contChunkSize, numberOfChunksPerCont,
			40, 10, 10);
    }
    else {
      playerId = 1; // just for now
      ConnectServer(server);
      screen->AddReadNotify(sock, HandleMessage);
      MsgQ *q = new MsgQ;
      q->AddCmd(CONNECT);
      *q << myName;
      SendQ(q);
    }
  }
  delete server;
}
