#include "empire.h"
#include "logic.h"

vector<_loc> find_attackables(_unit *u)
{
  vector<_loc> a;
  _loc t;
  int x, y, i, max, min;
  a.resize(0);
  a.reserve(4);
  if (u->attacktype == DIRECT)
  {  //search for attackable units on adjacent spaces
    i = 0;
    while (i < 4)
    {
      switch(i)
      {
        case 0:
          x = u->tilex + 1;
          y = u->tiley;
          break;
        case 1:
          x = u->tilex - 1;
          y = u->tiley;
          break;
        case 2:
          x = u->tilex;
          y = u->tiley - 1;
          break;
        case 3:
          x = u->tilex;
          y = u->tiley + 1;
          break;
      }
      if (attackable_unit_here(u, x, y, true) != -1)
      {  //finds all attackables, including teammates
        t.x = x;
        t.y = y;
        a.push_back(t);
      }
      i++;
    }
  }
  else if (u->attacktype == RANGED)
  {  //search for attackable units anywhere within range
    max = get_rangemax(u->type);
    min = get_rangemin(u->type);
    y = u->tiley - max;
    if (y < 0) y = 0;
    while ((y <= u->tiley + max) && (y < worldmap.h))
    {
      x = u->tilex - max;
      if (x < 0) x = 0;
      while ((x <= u->tilex + max) && (x < worldmap.l))
      {
        i = tile_distance(x, y, u->tilex, u->tiley);
        if ((i >= min) && (i <= max))
        {
          if (attackable_unit_here(u, x, y, true) != -1)
          {
            t.x = x;
            t.y = y;
            a.push_back(t);
          }
        }
        x++;
      }
      y++;
    }
  }
  return a;
}

void draw_attackables(vector<_loc> locations)
{
  static int r = 0;
  int i, m, t1, t2, u;
  int d = MAP_TILE_SIZE;
  r += 3;
  if (r > 256)
  {
    r -= 256;
  }
  i = 0;
  m = locations.size();
  while (i < m)
  {  //rotates a targeting thingy over each attackable enemy
    t1 = (locations[i].x - worldmap.scroll_x) * MAP_TILE_SIZE + worldmap.offset_x;
    t2 = (locations[i].y - worldmap.scroll_y) * MAP_TILE_SIZE + worldmap.offset_y;
    u = worldmap.tile[locations[i].x][locations[i].y].unit_here();
    if (player[u / 100].team == player[pturn].team)
    {  //if this attackable unit is on an allied team
      buffer_hline(t1, t2, t1 + 10, GREEN);
      buffer_hline(t1, t2 + 1, t1 + 10, GREEN);
      buffer_hline(t1 + (d - 11), t2, t1 + (d - 1), GREEN);
      buffer_hline(t1 + (d - 11), t2 + 1, t1 + (d - 1), GREEN);
      buffer_hline(t1, t2 + (d - 2), t1 + 10, GREEN);
      buffer_hline(t1, t2 + (d - 1), t1 + 10, GREEN);
      buffer_hline(t1 + (d - 11), t2 + (d - 2), t1 + (d - 1), GREEN);
      buffer_hline(t1 + (d - 11), t2 + (d - 1), t1 + (d - 1), GREEN);
      buffer_vline(t1, t2, t2 + 10, GREEN);
      buffer_vline(t1 + 1, t2, t2 + 10, GREEN);
      buffer_vline(t1 + (d - 2), t2, t2 + 10, GREEN);
      buffer_vline(t1 + (d - 1), t2, t2 + 10, GREEN);
      buffer_vline(t1, t2 + (d - 11), t2 + (d - 1), GREEN);
      buffer_vline(t1 + 1, t2 + (d - 11), t2 + (d - 1), GREEN);
      buffer_vline(t1 + (d - 2), t2 + (d - 11), t2 + (d - 1), GREEN);
      buffer_vline(t1 + (d - 1), t2 + (d - 11), t2 + (d - 1), GREEN);
    }  //(draws a green square-like target thingy)
    else
    {
      buffer_rotate_sprite(glb.bmp(12), t1 + MAP_TILE_SIZE / 2, t2 + MAP_TILE_SIZE / 2, r);
    }
    i++;
  }
}

int attackable_unit_here(_unit *attacker, int tx, int ty)
{
  return attackable_unit_here(attacker, tx, ty, false);
}

int attackable_unit_here(_unit *attacker, int tx, int ty, bool ignore_teams)
{
  int u = worldmap.tile[tx][ty].unit_here();
  _unit *defender;
  int d;
  if ((u != -1) && (u / 100 != attacker->color))
  {
    defender = &player[u / 100].unit[u % 100];
    if (player[attacker->color].team == player[defender->color].team)
    {  //if the players are on the same team
      if (!ignore_teams)
      {  //if teams are being recognized
        return -1;
      }
    }
    if (type_can_attack(attacker, defender))
    {  //if the attacker could, in theory, attack the defender
      d = tile_distance(attacker->tilex, attacker->tiley, tx, ty);
      if (attacker->attacktype == DIRECT)
      {  //if the attacker is direct and next to the defender, it can attack
        if (d == 1)
        {
          return u;
        }
      }
      else if (attacker->attacktype == RANGED)
      {
        if ((d >= get_rangemin(attacker->type)) && (d <= get_rangemax(attacker->type)))
        {  //if the attacker has the defender within its firing range, it can attack
          return u;
        }
      }
    }
  }
  return -1;
}

bool type_can_attack(_unit *a, _unit *d)
{
  int ta = a->type;
  int td = d->type;
  if (a->ammo > 0)
  {
    switch(d->basetype)
    {
      case LAND:
        if (a->basetype == LAND)
        {
          if (ta != MISSILES)
          {
            return true;
          }
        }
        else
        {
          if ((ta == B_COPTER) || (ta == BOMBER) || (ta == B_SHIP))
          {
            return true;
          }
        }
        break;
      case AIR:
        if (a->basetype == AIR)
        {
          if (ta != BOMBER)
          {
            if (ta == B_COPTER)
            {
              if ((td != BOMBER) && (td != FIGHTER))
              {
                return true;
              }
            }
            else
            {
              return true;
            }
          }
        }
        else if (a->basetype == LAND)
        {
          if ((td == BOMBER) || (td == FIGHTER))
          {
            if ((ta == MISSILES) || (ta == ANTI_AIR))
            {
              return true;
            }
          }
          else
          {
            if (!((ta == ARTILLERY) || (ta == ROCKETS)))
            {
              return true;
            }
          }
        }
        else if (ta == CRUISER)  //cruiser is the only sea unit w/ anti-air ability
        {
          return true;
        }
        break;
      case SEA:
        if (a->basetype == SEA)
        {
          if (ta == CRUISER)
          {  //cruisers can only attack air units and subs
            if (td == SUB)
            {
              return true;
            }
          }
          else
          {
            if ((td == SUB) && (d->submerged == 1))
            {  //battleships can't hit submerged subs
              if ((ta == SUB) || (ta == CRUISER))  //but subs and cruisers can
              {
                return true;
              }
              else
              {
                return false;
              }
            }
            return true;
          }
        }
        else if (a->basetype == LAND)
        {
          if ((ta == TANK) || (ta == MD_TANK) || (ta == ARTILLERY) || (ta == ROCKETS))
          {
            if ((td == SUB) && (d->submerged == 1))
            {  //can't hit an underwater sub from land
              return false;
            }
            else
            {
              return true;
            }
          }
        }
        else
        {
          if ((ta == BOMBER) || (ta == B_COPTER))
          {
            if ((td == SUB) && (d->submerged == 1))
            {  //can't hit a submerged sub from air either
              return false;
            }
            else
            {
              return true;
            }
          }
        }
        break;
    }
  }
  return false;
}
