#include "allegro.h"

#ifdef _WIN32
#include "winalleg.h"

#include <winsock.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#endif

#include "client.h"
#include "defs.h"
#include "engine.h"
#include "console.h"
#include "gfx.h"
#include "items.h"
#include "network.h"
#include "packet.h"
#include "player.h"
#include "rules.h"
#include "server.h"
#include "sound.h"
#include "weapons.h"
#include "ai.h"

#include "demos.h"

void tracePointPlayer(BITMAP *bmp, int x, int y, int d)
{
   int i;
   long c;
   
   if (trace)
   {
      c = getpixel(material,x,y);
      if (((c & MAT_BLOCK_WORM) == MAT_BLOCK_WORM) ||
          (x<0) || (x>=mapSizeX) ||
          (y<0) || (y>=mapSizeY)
         )
      {
         trace = 0;
      }
   }
}

void traceLinePlayer(int sX, int sY, int eX, int eY)
{
   trace = 1;
   do_line(material, sX, sY, eX, eY, 0, tracePointPlayer);
}

char chatActive;
char chatText[30];

void addPlayer(int num)
{
   int red = 0, blue = 0, i;
   worms[num].active = 1;
   if ((gameType == GAME_CTF) || (gameType == GAME_DOM))
   {
      for (i=0; i<GP_NUM_PLAYERS; i++)
      {
         if (worms[i].active)
         {
            if (worms[i].team == 0)
               blue++;
            else
               red++;
         }
      }
      worms[num].team = ((red >= blue) ? 0 : 1);
   }
}

void removePlayer(int n)
{
   int i;
   interact *tmpItem;

   tmpItem = itemList;
   while (tmpItem)
   {
      if (tmpItem->owner == &worms[n])
         tmpItem->ownerDead(&worms[n]);
      tmpItem = tmpItem->next;
   }

   worms[n].active = 0;
   for (i=0; i < GP_NUM_PLAYERS; i++)
   {
      if (worms[i].flags[FL_GOT_ENEMY])
      if (worms[i].lineCatch == &worms[n])
      {
         worms[i].flags[FL_GOT_ENEMY] = 0;
         worms[i].ropevel = worms[n].vel;
      }
   }
}

void getSpawnPoint(worm *player, int *x, int *y, char useIt)
{
   interact *tmpItem;
   int count;

   if (gameType != GAME_CTF)
   {
      if (Engine.wormRandomSpawn)
      {
         if (!useIt)
         {
            *x = player->coords.x;
            *y = player->coords.y;
            return;
         }
         else
         {
            bool found = false;
            int tx, ty;
            int i;
            
            while (!found)
            {
               tx = RANDOM() % mapSizeX;
               ty = RANDOM() % mapSizeY;
               found = true;
               for (i = -Engine.wormSizeX; (i <= Engine.wormSizeX) && (found); i++)
               {
                  traceLinePlayer(tx+i, ty+Engine.wormSizeYMin, tx+i, ty-Engine.wormSizeYMax);
                  if (!trace)
                     found = false;
               }
            }
            *x = tx;
            *y = ty;
            return;
         }
      }
      else
      {
         *x = respawnPoints[respawnPoint*2];
         *y = respawnPoints[respawnPoint*2+1];
         if (useIt)
         {
            respawnPoint++;
            if (respawnPoint >= respawnNumPoints)
               respawnPoint = 0;
         }
      }
   }
   else
   {
      tmpItem = itemList;
      count = 0;

      while (tmpItem)
      {
         if (tmpItem->type == ITEM_TEAMSPAWN)
         if (tmpItem->amount == player->team%2)
            count++;
         tmpItem = tmpItem->next;
      }

      if (count == 0) // no team spawnpoints
      {
         *x = respawnPoints[respawnPoint*2];
         *y = respawnPoints[respawnPoint*2+1];
         if (useIt)
         {
            respawnPoint++;
            if (respawnPoint >= respawnNumPoints)
               respawnPoint = 0;
         }
      }
      else // got some
      {
         count = RANDOM()%count;
         tmpItem = itemList;
         while (tmpItem)
         {
            if (tmpItem->type == ITEM_TEAMSPAWN)
            if (tmpItem->amount == player->team%2)
            {
               count--;
               if (count < 0)
                  break;
            }
            tmpItem = tmpItem->next;
         }
         if (!tmpItem)
         {
            Console.WriteF("No spawnpoint for team %d!", player->team);
            return;
         }
         *x = tmpItem->spawnX;
         *y = tmpItem->spawnY;
      }
   }
}

char always1 = 1;

void respawnPlayer(int n)
{
   int i;
   weapon *weap;


   worms[n].num = n;
   worms[n].enemy = NULL;
   getSpawnPoint(&worms[n], &worms[n].coords.x, &worms[n].coords.y, 1);
   worms[n].pos.x = worms[n].oldpos.x = worms[n].coords.x*1000;
   worms[n].pos.y = worms[n].oldpos.y = worms[n].coords.y*1000;
   worms[n].vel.x = worms[n].vel.y = 0;
   worms[n].aim = 16;
   worms[n].next_rope = 0;
   worms[n].freezeEnd = 0;
   worms[n].health = GP_WORM_HEALTH;
   worms[n].flags[FL_ROPE_OUT] = 0;
   worms[n].flags[FL_ROPE_HIT] = 0;
   worms[n].flags[FL_GOT_ENEMY] = 0;
   worms[n].aiState = 0;
   worms[n].localTime = gameTime;
   if (instantReload)
   {
      for (i=0; i<5; i++)
      {
         worms[n].reload[i] = 0;
         worms[n].ammo[i] = weapons[worms[n].weaps[i]].maxAmmo;
         worms[n].next_fire[i] = gameTime;
      }
      weap = &weapons[worms[n].weaps[worms[n].curWeap]];
      if (weap->ejectShells >= 1)
//         ((weap->ejectShells > 2) && (abs(RANDOM())%(weap->ejectShells - 2) == 0)))
      {
         fireShrapnel(&worms[n], worms[n].pos.x, worms[n].pos.y + Engine.wormFireOffs * 1000, 0, -1000, shellObject, 0, 1);
      }
//      playSound(weapons[worms[n].weaps[worms[n].curWeap]].reloadSnd, worms[n].x, worms[n].y);
   }
   createSpecial(&worms[n], worms[n].coords.x, worms[n].coords.y + Engine.wormFireOffs, respawnObject, 0, &always1);
}

void playerTiming()
{
   int i;
   for (i=0; i<GP_NUM_PLAYERS; i++)
   if (worms[i].active)
   if (worms[i].health>0)
   {
      if (gameType == GAME_TAG)
      if (worms[i].flags[FL_PREDATOR])
      {
         if (!gameOver)
         if ((gameTime - worms[i].localTime)%225 == 224)
         {
            giveScore(&worms[i], 1);
            checkRules();
         }
      }
      if (worms[i].ammo[worms[i].curWeap] == 0)
      if (weapons[worms[i].weaps[worms[i].curWeap]].loadTime != -1)
      {
         worms[i].reload[worms[i].curWeap]++;
         if (worms[i].reload[worms[i].curWeap] >= weapons[worms[i].weaps[worms[i].curWeap]].loadTime)
         {
            Sound.playSound(weapons[worms[i].weaps[worms[i].curWeap]].reloadSnd, worms[i].coords.x, worms[i].coords.y);
            worms[i].reload[worms[i].curWeap] = 0;
            worms[i].ammo[worms[i].curWeap] = weapons[worms[i].weaps[worms[i].curWeap]].maxAmmo;
            worms[i].next_fire[worms[i].curWeap] = gameTime;
            if (weapons[worms[i].weaps[worms[i].curWeap]].ejectShells >= 1)
            {
               fireShrapnel(&worms[i], worms[i].pos.x, worms[i].pos.y + Engine.wormFireOffs * 1000, 0, -1000, shellObject, 0, 1);
            }
         }
      }
   }
   else
   {
      if (!gameOver)
      if ((worms[i].lives > 0) || (gameType != GAME_KTA))
      if ((worms[i].next_spawn == gameTime) || (worms[i].buttons[GK_CHANGE]))
         respawnPlayer(i);
   }
}

void sendChat(char *text)
{
   int i;

   if (strlen(text) == 0) return;

   if (!isServer)
   {
      Packet(CLIENT_CHAT);
      for (i=0; i<50; i++)
         PacketAddByte(text[i]);
      Client.SendPacket(packetsend, CLIENT_CHAT_SIZE, 1);
   }
   else
   {
      Packet(PACKET_CHAT);
      PacketAddByte(viewport[0].player);
      for (i=0; i<50; i++)
         PacketAddByte(text[i]);
      ServerBroadcast(packetsend, PACKET_CHAT_SIZE);
      Console.WriteF("%s: %s", worms[viewport[0].player].name, text);
      Sound.playSound(talkSnd, worms[viewport[0].player].coords.x, worms[viewport[0].player].coords.y);
   }
}

//             QUICKTEXT       //
void processQuickText() 
{            
      if(key[players[0].keys[GK_QUICK]]) 
      {
         if(!quicktextActive)
         {
            set_trans_blender(0, 0, 0, 127);
            for(int i=0; i<10; i++)
            {
               drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
               rectfill(buffer, 30, 2+i*15, 290, 15+i*15, 0);
               drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
               sprintf(buf, "%d", i==9 ? 0 : i+1);
               drawTextC(buffer, buf, 40, 7+i*15);
               drawText(buffer, quicktexts[i==9 ? 0 : i+1], 60, 7+i*15);
               if(key[KEY_0+i])
               {
                  sendChat(quicktexts[i]);
                  quicktextActive=1;
               }
            }
         }
      } else {
         quicktextActive=0; 
      }
}
//////////////////////////////////////

void processChat()
{
   int keyCode;
   
   if (!chatActive) return;
   while (keypressed())
   {
      keyCode = readkey() & 0xFF;
      if (keyCode == 13)
      {
         chatActive = 0;
         sendChat(chatText);
         chatText[0] = 0;
      }
      else
      {
         if (keyCode != 8)
         {
            if (strlen(chatText)<49)
            {
               chatText[strlen(chatText)+1] = 0;
               chatText[strlen(chatText)] = keyCode;
            }
         }
         else
         {
            if (strlen(chatText) > 0)
               chatText[strlen(chatText)-1] = 0;
            else
               chatActive = 0;
         }
      }
   }
   sprintf(buf, "SAY: %s_", chatText);
   drawText(buffer, buf, 2, 142);
}
