/*
Angry Moth
Copyright (C) 2005 Linley Henzell

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public Licence as published by
    the Free Software Foundation; either version 2 of the Licence, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public Licence for more details.

    You should have received a copy of the GNU General Public Licence
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    The GPL version 2 is included in this distribution in a file called
    LICENCE.TXT. Use any text editor or the TYPE command to read it.

    You should be able to reach me by sending an email to
    l_henzell@yahoo.com.au.

File: input.c
History:

This file contains:
 - keyboard input. Commands are passed to cmds.c - see intro to that file
for a bit more information.

*/

#include <math.h>
#include "config.h"

#include "allegro.h"
#include "pbullet.h"
#include "math.h"

#include "globvars.h"

#include "cloud.h"
#include "stuff.h"

#include "sound.h"


#define TARGET_ARRAY_SIZE 10

//#define SCREENSHOT
//#define DEBUG_KEYS



#ifdef SCREENSHOT
#include <string.h>
#include "palette.h"
extern RGB palet [256];
extern RGB palet2 [256];
#endif

void check_red_fire(void);

void enact_commands(int xc, int yc, int cfire, int cswitch, int ccharge);
void move_player(int xm, int ym);
void player_fire1(void);
void player_fire2(void);
void player_switch(void);
void player_release_charge(void);
int find_enemies(int w, int targets [TARGET_ARRAY_SIZE], int x, int y, int number, int start_number, int force);
void shoot_multi_bullet(int type, int angle, int x_disp);
void fire_turret2(int angle);
void fire_turret(void);

void get_input(void)
{

if (key [KEY_ESC])
 exit(301);

#ifdef SCREENSHOT

static int scrs = 0;
static int sshot_counter = 0;


 char sfile [20];
 char istr [20];

 if (sshot_counter > 0)
  sshot_counter --;

 if (key [KEY_F1] && sshot_counter <= 0)
 {
  BITMAP *scrshot_bmp;
   scrshot_bmp = create_bitmap(640, 480);
   blit(screen, scrshot_bmp, 0,0,0,0,640,480);

  strcpy(sfile, "scr");
  strcat(sfile, itoa(scrs, istr, 10));
  strcat(sfile, ".bmp");
  if (arena.level == 1)
   save_bitmap(sfile, scrshot_bmp, palet);
    else
     save_bitmap(sfile, scrshot_bmp, palet2);
  clear_to_color(screen, TRANS_WHITE);
  scrs ++;
  sshot_counter = 15;
  destroy_bitmap(scrshot_bmp);
 }

#endif

#ifdef DEBUG_KEYS

 if (arena.counter % 20 == 0)
 {

  if (key [KEY_1])
  {
   player.weapon [0] = WPN_RED;
   if (player.power [0] < 5)
    player.power [0] ++;
  }
  if (key [KEY_2])
  {
   player.weapon [0] = WPN_BLUE;
   if (player.power [0] < 5)
    player.power [0] ++;
  }
  if (key [KEY_3])
  {
   player.weapon [0] = WPN_GREEN;
   if (player.power [0] < 5)
    player.power [0] ++;
  }
  if (key [KEY_4])
  {
   player.weapon [0] = WPN_WHITE;
   if (player.power [0] < 5)
    player.power [0] ++;
  }

  if (key [KEY_5])
  {
   player.weapon [1] = WPN_RED;
   if (player.power [1] < 5)
    player.power [1] ++;
  }
  if (key [KEY_6])
  {
   player.weapon [1] = WPN_BLUE;
   if (player.power [1] < 5)
    player.power [1] ++;
  }
  if (key [KEY_7])
  {
   player.weapon [1] = WPN_GREEN;
   if (player.power [1] < 5)
    player.power [1] ++;
  }
  if (key [KEY_8])
  {
   player.weapon [1] = WPN_WHITE;
   if (player.power [1] < 5)
    player.power [1] ++;
  }


 }

#endif





    if (player.in_play == 0 || player.respawning > 0)
     return;

    int xc = 0;
    int yc = 0;
    int cfire = 0, cswitch = 0, ccharge = 0;

    player.blue_was_firing = player.blue_fire;

    if (key [player.key [CKEY_FIRE]] || player.autofire != 0)
     cfire = 1;
      else
       player.blue_fire = 0;

    if (key [player.key [CKEY_AUTOFIRE]])
    {
     if (player.autofire_toggle == 0)
     {
         if (player.autofire == 0)
          player.autofire = 1;
           else
            player.autofire = 0;
         player.autofire_toggle = 20;
     }
    }

    if (key [player.key [CKEY_SWITCH]])
     cswitch = 1;

    if (key [player.key [CKEY_CHARGE]])
     ccharge = 1;

   if (key [player.key [CKEY_LEFT]])
   {
    if (key [player.key [CKEY_RIGHT]] || player.x <= X_MIN)
     xc = 0;
      else xc = -1000;
   }
    else
     if (key [player.key [CKEY_RIGHT]] && player.x < X_MAX)
      xc = 1000;

   if (key [player.key [CKEY_UP]])
   {
    if (key [player.key [CKEY_DOWN]] || player.y <= Y_MIN)
     yc = 0;
      else yc = -1000;
   }
    else
     if (key [player.key [CKEY_DOWN]] && player.y < Y_MAX)
      yc = 1000;

   if (xc > 0 && yc > 0)
   {
    xc = 707;
    yc = 707;
   }
   if (xc < 0 && yc > 0)
   {
    xc = -707;
    yc = 707;
   }
   if (xc < 0 && yc < 0)
   {
    xc = -707;
    yc = -707;
   }
   if (xc > 0 && yc < 0)
   {
    xc = 707;
    yc = -707;
   }

   if (xc > 0)
   {
    if (player.bank < 30)
     player.bank += 4;
   }
    else
    {
     if (player.bank > 0)
      player.bank -= 4;
    }

   if (xc < 0)
   {
    if (player.bank > -30)
     player.bank -= 4;
   }
    else
    {
     if (player.bank < 0)
      player.bank += 4;
    }

   enact_commands(xc, yc, cfire, cswitch, ccharge);
}




void enact_commands(int xc, int yc, int cfire, int cswitch, int ccharge)
{
  if (player.charge > 0)
   move_player(xc * 2, yc * 2);
    else
    {
     move_player(xc * 5, yc * 5);
     if (player.weapon [0] == WPN_RED && player.power [0] > 0)
     {
      check_red_fire();
     }
    }

  if (player.switch_recycle <= 0)
  {
   if (cfire && player.charge == 0)
   {
    if (player.recycle == 0)
     player_fire1();
    if (player.recycle2 == 0)
     player_fire2();
   }

   if (cswitch)
    player_switch();
   if (ccharge)
   {
//       int old_charge = player.charge;
    if (player.charge <= 800)
     player.charge += 11;
     if (player.charge > 800)
      player.charge = 800;
//     if ((int) player.charge / 100 != (int) old_charge / 100)
//     {
//       play_effectf(NWAV_BLOP, 1000 + player.charge);
//     }
//     player.charge += 8;
   }
   if (!ccharge && player.charge > 0)
    player_release_charge();
  }
}


void move_player(int xm, int ym)
{
     player.x += xm;
     player.y += ym;
     if (player.x <= X_MIN)
      player.x = X_MIN;
     if (player.y <= Y_MIN)
      player.y = Y_MIN;
     if (player.x >= X_MAX)
      player.x = X_MAX;
     if (player.y >= Y_MAX)
      player.y = Y_MAX;
}

void player_fire1(void)
{
 if (player.switch_recycle > 0)
  return; // switching

 int x;

 switch(player.weapon [0])
 {
  case WPN_WHITE:
   player.white_recycle1 --;
   if (player.white_recycle1 <= 0)
   {
    fire_turret();
    player.white_recycle1 = 11 - player.power [0];
   }
   player.white_recycle2 --;
   if (player.white_recycle2 <= 0)
   {
    create_pbullet(player.sides, PBULLET_BASIC, player.x - 5000 + abs(player.bank * 40), player.y - 4000, 0, 1000);
    create_pbullet(player.sides, PBULLET_BASIC, player.x + 5000 - abs(player.bank * 40), player.y - 4000, 0, 1000);
    create_cloud(player.sides, CLOUD_EXPLODE, 0, player.x - 5000 + abs(player.bank * 40), player.y - 6000, 0, 0, 7 + grand(3));
    create_cloud(player.sides, CLOUD_EXPLODE, 0, player.x + 5000 - abs(player.bank * 40), player.y - 6000, 0, 0, 7 + grand(3));
    play_effectwfvx(player.sides, NWAV_FIRE, 1500, 200, player.x);
// note - copied in WPN_RED
    player.white_recycle2 = 8;
   }
   player.recycle = 0;
   break;
  case WPN_RED:
   create_pbullet(player.sides, PBULLET_BASIC, player.x - 5000 + abs(player.bank * 40), player.y - 4000, 0, 1000);
   create_pbullet(player.sides, PBULLET_BASIC, player.x + 5000 - abs(player.bank * 40), player.y - 4000, 0, 1000);
   create_cloud(player.sides, CLOUD_EXPLODE, 0, player.x - 5000 + abs(player.bank * 40), player.y - 6000, 0, 0, 7 + grand(3));
   create_cloud(player.sides, CLOUD_EXPLODE, 0, player.x + 5000 - abs(player.bank * 40), player.y - 6000, 0, 0, 7 + grand(3));
// note - copied in WPN_WHITE
//   play_effectwfx(player.sides, NWAV_FIRE, 1000, player.x);
   play_effectwfvx(player.sides, NWAV_FIRE, 1500, 200, player.x);
   player.recycle = 8;
   break;
  case WPN_BLUE:
   player.blue_fire ++;
   if (player.blue_fire > 10)
    player.blue_fire = 10;
   break;
  case WPN_GREEN:
   if (player.green_side == 0)
   {
    x = player.x - 5000 + abs(player.bank * 40);
    player.green_side = 1;
   }
     else
     {
      x = player.x + 5000 - abs(player.bank * 40);
      player.green_side = 0;
     }
   create_pbullet(player.sides, PBULLET_CIRCLE, x, player.y - 4000, player.power [0], 1000);
   create_cloud(player.sides, CLOUD_EXPLODE, 1, x, player.y - 6000, 0, 0, 7 + grand(3));
   player.recycle = 10 - player.power [0];
   play_effectwfvx(player.sides, NWAV_CIRCLE, 1800 + player.power [0] * 230, 120, player.x);
   break;
 }

}

void check_red_fire(void)
{
 if (player.switch_recycle > 0)
  return;


 switch(player.recycle)
 {
  case 7:
   if (player.power [0] > 2)
   shoot_multi_bullet(PBULLET_MULTI1, ANGLE_32 - ANGLE_64, 5000 + abs(player.bank * 40));
   break;
  case 6:
   if (player.power [0] > 0)
   shoot_multi_bullet(PBULLET_MULTI2, ANGLE_32, 5000 + abs(player.bank * 40));
   break;
  case 5:
   if (player.power [0] > 1)
   shoot_multi_bullet(PBULLET_MULTI3, ANGLE_32 + ANGLE_64, 5000 + abs(player.bank * 40));
   break;
  case 4:
   if (player.power [0] > 3)
   shoot_multi_bullet(PBULLET_MULTI4, ANGLE_16, 5000 + abs(player.bank * 40));
   break;
  case 3:
   if (player.power [0] > 4)
   shoot_multi_bullet(PBULLET_MULTI5, ANGLE_16 + ANGLE_64, 5000 + abs(player.bank * 40));
   break;

 }

}

void shoot_multi_bullet(int type, int angle, int x_disp)
{


 int b = create_pbullet(player.sides, type, player.x + x_disp, player.y - 4000, 0, 1000);
 int speed = 12000 - (type - PBULLET_MULTI1) * 1000;

 if (b != -1)
 {
  pbullet[player.sides][b].x_speed = xpart(angle - ANGLE_4, speed);
  pbullet[player.sides][b].y_speed = ypart(angle - ANGLE_4, speed);
 }

 create_cloud(player.sides, CLOUD_EXPLODE, 0, player.x + x_disp, player.y - 6000, 0, 0, 5 + grand(3));

 b = create_pbullet(player.sides, type, player.x - x_disp, player.y - 4000, 1, 1000);

 if (b != -1)
 {
  pbullet[player.sides][b].x_speed = xpart(ANGLE_1 - angle - ANGLE_4, speed);
  pbullet[player.sides][b].y_speed = ypart(ANGLE_1 - angle - ANGLE_4, speed);
 }

 create_cloud(player.sides, CLOUD_EXPLODE, 0, player.x - x_disp, player.y - 6000, 0, 0, 5 + grand(3));

 play_effectwfvx(player.sides, NWAV_FIRE, 2000, 70, player.x);


}

void player_fire2(void)
{
 if (player.switch_recycle > 0)
  return; // switching

 int side = 0, i;

 if (player.sides == 0)
  side = 1;

 switch(player.weapon [1])
 {
  case WPN_RED:
   create_pbullet(side, PBULLET_HEAVY, player.x, player.y - 5000, player.power [1], 1000);
   switch(player.power [1])
   {
    case 0:
    case 1: create_cloud(side, CLOUD_EXPLODE, 0, player.x, player.y - 8000, 0, 0, 12 + grand(3)); break;
    case 2:
    case 3: create_cloud(side, CLOUD_EXPLODE, 1, player.x, player.y - 8000, 0, 0, 12 + grand(3)); break;
    case 4:
    case 5: create_cloud(side, CLOUD_EXPLODE, 2, player.x, player.y - 8000, 0, 0, 12 + grand(3)); break;
   }
//   play_effectwfx(side, NWAV_FIRE2, 1000 + player.power [1] * 70, player.x);
   play_effectwfx(side, NWAV_FIRE, 300 + player.power [1] * 40, player.x);
   player.recycle2 = 24 - player.power [1];
   break;
  case WPN_BLUE:
   player.blue2_fire = 5;
   player.recycle2 = 24 - player.power [1];
   play_effectwfvx(side, NWAV_PBEAM2, 1300 + player.power [1] * 100, 100, player.x);
   break;
  case WPN_GREEN:
   create_pbullet(side, PBULLET_GREEN2, player.x, player.y - 5000, player.power [1], 1000);
   create_cloud(side, CLOUD_EXPLODE, 1, player.x, player.y - 8000, 0, 0, 15 + grand(3));
   player.recycle2 = 20;
   play_effectwfvx(side, NWAV_CIRCLE, 1000 - player.power [1] * 30, 120, player.x);
   break;
  case WPN_WHITE:
/*   create_pbullet(side, PBULLET_WHITE2, player.x, player.y - 5000, 22000, 1000);
   create_pbullet(side, PBULLET_WHITE2, player.x, player.y - 5000, 20000, 1000);
   create_pbullet(side, PBULLET_WHITE2, player.x, player.y - 5000, 18000, 1000);*/
   for (i = 0; i < player.power [1] + 3; i ++)
   {
    create_pbullet(side, PBULLET_WHITE2, player.x, player.y - 5000, 22000 - i * 2500, 1000);
   }
   player.recycle2 = 30 - player.power [1];
   create_cloud(side, CLOUD_EXPLODE, 2, player.x, player.y - 8000, 0, 0, 15 + grand(3));
   play_effectwfvx(side, NWAV_BLAST2, 1500 - player.power [1] * 90, 70, player.x);
   break;
 }


}


void player_switch(void)
{
 if (player.sides == 0)
  player.switching = 1;
   else
    player.switching = 0;

// player.pole = POLE_NONE;
 player.switch_recycle = 20;
 player.blue_fire = 0;


}

void player_release_charge(void)
{

 if (player.switch_recycle > 0)// || player.energy == 0)
  return;

 if (player.charge < 100)
 {
  player.charge = 0;
  return;
 }

 if (player.charge >= 300)
 {
  if (player.sides == 0)
  {
   create_pbullet(1, PBULLET_WAVE, player.x, player.y - 3000, player.charge, 1000);
   play_effectwfvx(1, NWAV_WAVE, (1100 - player.charge) * 2, 250, player.x);
  }
    else
    {
     create_pbullet(0, PBULLET_WAVE, player.x, player.y - 3000, player.charge, 1000);
     play_effectwfvx(0, NWAV_WAVE, (1100 - player.charge) * 2, 250, player.x);
    }
 }


 int i;

 int angles [9] = {ANGLE_2, ANGLE_2 + ANGLE_16, ANGLE_2 - ANGLE_16, ANGLE_2 + ANGLE_8, ANGLE_2 - ANGLE_8,
               ANGLE_2 + ANGLE_8 + ANGLE_16, ANGLE_2 - ANGLE_8 - ANGLE_16,
               ANGLE_4, -ANGLE_4};

 int targets [TARGET_ARRAY_SIZE];
// int no_targets = 0;

 int t;

 for (t = 0; t < TARGET_ARRAY_SIZE; t ++)
 {
  targets [t] = -1;
 }

 int number = player.charge / 100;

 int which_angle = 0;
  if (number % 2 == 0)
   which_angle = 1;


 if (number > 8)
  number = 8;

 find_enemies(player.sides, targets, player.x, player.y, number, 0, 0);
 //int found = find_enemies(player.sides, targets, player.x, player.y, number, 0, 0);
/*
 if (found < number)
 {
  if (player.pole == POLE_WHITE)
   found += find_enemies(0, targets, POLE_BLACK, player.x, player.y, number, found, 0);
    else
     found += find_enemies(0, targets, POLE_WHITE, player.x, player.y, number, found, 0);
 }

 if (found < number)
 {
  if (player.pole == POLE_WHITE)
   found += find_enemies(0, targets, POLE_WHITE, player.x, player.y, number, found, 1);
    else
     found += find_enemies(0, targets, POLE_BLACK, player.x, player.y, number, found, 1);
 }
*/

 for (i = 0; i < number; i ++)
 {
  create_seeker(player.sides, angles [which_angle] - ANGLE_4, targets [i]);
  which_angle ++;


 }

 play_effectwfvx(player.sides, NWAV_CIRCLE, 400 + number * 50, 100 + number * 15, player.x);


 player.charge = 0; //energy = player.energy % SEEKER_ENERGY;

}

int find_enemies(int w, int targets [TARGET_ARRAY_SIZE], int x, int y, int number, int start_number, int force)
{

 int t;
 int targets_found = 0;
 int enemies_found = 0;

/* for (t = 0; t < TARGET_ARRAY_SIZE; t ++)
 {
  targets [t] = -1;
 }*/

 int e;

 for (e = 0; e < NO_ENEMIES; e ++)
 {
  if (enemy[w][e].type == ENEMY_NONE)
  {
   enemy[w][e].distance = 700000;
   continue;
  }

  enemy[w][e].distance = hypot(enemy[w][e].y - y, enemy[w][e].x - x) / 100;
  enemies_found ++;

 }

 if (enemies_found == 0)
  return 0;

 int closest = -1;
 int smallest_distance = 700000;

 for (t = start_number; t < TARGET_ARRAY_SIZE; t ++)
 {
  for (e = 0; e < NO_ENEMIES; e ++)
  {
   if (enemy[w][e].distance < smallest_distance)
   {
    closest = e;
    smallest_distance = enemy[w][e].distance;
   }
  }
  if (smallest_distance == 700000)
  {
   return targets_found;
  }
  targets [t] = closest;
  enemy[w][closest].distance = 700000;
  targets_found ++;
  closest = -1;
  smallest_distance = 700000;
 }

 return targets_found;
}


void fire_turret(void)
{

// int targets_found = 0;
 int enemies_found = 0;

 int e;

 for (e = 0; e < NO_ENEMIES; e ++)
 {
  if (enemy[player.sides][e].type == ENEMY_NONE)
  {
   enemy[player.sides][e].distance = 700000;
   continue;
  }

  enemy[player.sides][e].distance = (abs(enemy[player.sides][e].y - player.y) + abs(enemy[player.sides][e].x - player.x)) / 100;//hypot(enemy[w][e].y - y, enemy[w][e].x - x) / 100;
  enemies_found ++;

 }

 if (enemies_found == 0)
 {
    fire_turret2(-ANGLE_4);
    return;
 }

 int closest = -1;
 int smallest_distance = 700000;

  for (e = 0; e < NO_ENEMIES; e ++)
  {
   if (enemy[player.sides][e].distance < smallest_distance)
   {
    closest = e;
    smallest_distance = enemy[player.sides][e].distance;
   }
  }

  if (smallest_distance == 700000)
  {
   fire_turret2(-ANGLE_4);
   return;
  }

 int angle = radians_to_angle(atan2((enemy[player.sides][closest].y - player.y), (enemy[player.sides][closest].x - player.x)));

 fire_turret2(angle);

// return targets_found;
}

void fire_turret2(int angle)
{
 int x = player.x + xpart(angle, 5000);
 int y = player.y + ypart(angle, 5000);

 int b = create_pbullet(player.sides, PBULLET_TURRET, x, y, angle, 1000);

 if (b != -1)
 {
  pbullet[player.sides][b].x_speed = xpart(angle, 8000);
  pbullet[player.sides][b].y_speed = ypart(angle, 8000);
  create_cloud(player.sides, CLOUD_EXPLODE, 2, x, y, 0, 0, 7 + grand(3));
 }

 play_effectwfvx(player.sides, NWAV_FIRE, 900, 200, player.x);


}
