#include "empire.h"

int numplayers;
int loaded_time;

_button start[7];
_button back;
_button ok;
_button opt[10];

_ingameoptions gameoptions;

extern void load_saved_characters(const char *savefilename);
extern void draw_minimap(int x, int y, string file);
extern void refresh_maplist();
extern int ingame_options();
extern int do_gameoptions(bool ingame = false);

void description(int c, int x, int y);
void list_players(int numplayers);
int do_first();
int do_load();
int do_options();
int do_gameload();
//int do_transition(int target);
string describe_strength(int num);
string describe_weakness(int num);

int is_beach(int x, int y);
int beach_already_listed(int x, int y);

void display_powers(int thechar, int x, int y, int iconsperrow);
void get_connected_beaches();
void add_surrounding_beaches(int bnum, int x, int y);
void get_teleports();

vector<_connectedlocs> beaches;
vector<_loc> teleports;

int menu()
{
  static int menunum = MENU_FIRST;
  static int startsongin = 2;
  //int oldmenunum = menunum;
  int t;
  
  if (startsongin == 0)
  {  //delay the song by 2 logic loops (so it isn't triggered early by transition)
    play_song(title_music);
    startsongin--;
  }
  else if (startsongin > 0)
  {
    startsongin--;
  }
  
  switch (menunum)
  {
    case MENU_FIRST:
      menunum = do_first();
      break;
    case MENU_LOAD:
      menunum = do_load();
      break;
    case MENU_OPTIONS:
      menunum = do_options();
      break;
    case MENU_GAME_OPTIONS:
      menunum = do_gameoptions();
      break;
    case MENU_INGAME_OPTIONS:
      menunum = ingame_options();
      break;
    case MENU_GAME_LOAD:
      menunum = do_gameload();
      break;
    case QUIT:
      return QUIT;
      break;
    default:        //default cases would lead out of the menu, so
      t = menunum;  //the menu has to open in FIRST next time
      menunum = MENU_FIRST;
      return t;
      break;
  }
  return MENU;
}





int do_first()
{
  static bool first = true;
  static int x;
	
  bool mouse = true;
  if (first)
  {
    start[0].init(370, 125, 100, 20, "Skirmish", 1);
    start[1].init(357, 160, 100, 20, "Load Game", 1);
    start[2].init(322, 265, 100, 20, "Quit", 1);
    start[3].init(305, 320, 100, 20, "Options", 1);
    start[4].init(290, 370, 100, 20, "Map Editor", 1);
    start[5].init(280, 400, 100, 20, "Player Editor", 1);
    start[6].init(340, 210, 100, 20, "Missions", 1);
    mouse = false;  //don't show the mouse the very first loop
    first = false;
    x = (640 - glb.bmp(0)->Width()) / 2;
  }
  
  glb.draw(0, x, 100);
  glb.draw(1, 58, 0);
		
  start[0].check();
  start[1].check();
  start[2].check();
  start[3].check();
  start[4].check();
  start[5].check();
  start[6].check();
	
  if (start[0].clicked())
  {
    first = true;
    return MENU_LOAD;
  }
  if (start[1].clicked())
  {
    first = true;
    return MENU_GAME_LOAD;
  }
  if ((start[2].clicked()) || (key[KEY_ESC]))
  {
    first = true;
    return QUIT;
  }
  if (start[3].clicked())
  {
    first = true;
    return MENU_GAME_OPTIONS;
  }
  if (start[4].clicked())
  {
    first = true;
    return MAPEDIT;
  }
  if (start[5].clicked())
  {
    first = true;
    return PLAYEREDIT;
  }
  if (start[6].clicked())
  {
    first = true;
    return MISSION;
  }
	
  if (mouse)
  {
    draw_mouse();
  }
  
  return MENU_FIRST;
}





int do_load()
{
	static bool first = true;
  static int lastsel;
  static int mapnum;
  static int players;
	static _listbox mapbox;
  int a, b, c, d, i, j, temp, sel;
	bool ok;
	char *s, *p;
  char tempchar[30];
  string name, ainame;
  
  if (first)
  {
//    highlighted = -1;
    opt[0].init(10, 455, 100, 20, "Back");
		opt[1].init(530, 455, 100, 20, "Next");
    empdebug("Loading the list of maps...");
		refresh_maplist();
		empdebug("  ...done");
		mapnum = maplist.size();
		mapbox.init(195, 55, 175, 330);
		i = 0;
		while (i < mapnum)
		{
			mapbox.additem(maplist[i].c_str());
			i++;
		}
		if (mapnum == 0)
		{
			mapbox.additem("NO MAPS FOUND!");
		}
    first = false;
  }
  
  glb.draw(10, 0, 0);
  buffer_textout_ex(big, "SELECT THE BATTLEGROUND", 180, 410, BLACK);
  
	mapbox.check();
	
	opt[0].check();
	if (opt[0].clicked())
  {  //return to main menu
    first = true;
    return MENU_FIRST;
  }

	if (mapnum > 0)
	{
		sel = mapbox.getsel();
		if (sel != -1)
		{
			s = mapbox.selected();
			p = (char*)malloc(sizeof(char) * (10 + strlen(s)));
			sprintf(p, "maps/");
      strcat(p, s);
      strcat(p, ".map");

			if (sel != lastsel)
			{
				lastsel = sel;
				if (s != NULL)
				{
					ifstream m(p);
          ok = true;
          if (m.bad())
          {
            ok = false;
            m.close();
          }
          if (ok)
          {
            m >> a >> b >> players;
            m.close();
          }
				}
			}
			
			opt[1].check();
			if (opt[1].clicked())
			{  //load the map and go the the player select screen
				ok = true;
        ifstream m(p);
        if (m.bad())
        {
          ok = false;
        }
        if (ok)
        {
          worldmap.reset();
          player[0].reset();  //get rid of any previous unit settings
          player[1].reset();
          player[2].reset();
          player[3].reset();
          worldmap.set_name(s);
          m >> worldmap.l >> worldmap.h >> numplayers;
          i = 0;
          while (i < numplayers)
          {  //initialize all players participating in this game
            player[i].playing = 1;
            player[i].everplaying = 1;
            player[i].cash = 0;
            player[i].power = 0;
            i++;
          }
          i = 0;
          while (i < worldmap.h)
          {
            j = 0;
            while (j < worldmap.l)
            {
              m >> temp;
              worldmap.tile[j][i].change_type(temp / 100, temp % 100);
              j++;
            }
            i++;
          }
          i = 0;
          while (i < 50 * numplayers)  //loading any placed units
          {
            m >> a;
            if (a != -1)  //if there is a saved unit for this i
            {
              m >> b >> c >> d;
              j = player[d].create_unit(c, a, b, d);
            }
            else  //if a reads -1, there are no more saved units
            {
              i = 50 * numplayers;
            }
            i++;
          }

          name = worldmap.get_name();
					load_ai(name);

          first = true;
          get_connected_beaches();
					get_teleports();
          minimap.create();
          return MENU_OPTIONS;
				}
			}

			buffer_rectfill(391, 146, 609, 384, BLACK);
      buffer_rect(390, 145, 610, 385, VDGREY);
      buffer_textout_ex(normal, s, 400, 150, WHITE);
      sprintf(tempchar, "%-1d Players", players);
      buffer_textout_ex(normal, tempchar, 400, 163, WHITE);
      draw_minimap(400, 178, p);
			
			free(p);
		}
	}
	
  draw_mouse();
  return MENU_LOAD;
}

int do_options()
{  //would be better off called something like choose_player(), but I'm lazy
  static int drawfirst = 1;
  static int delay = 0;
  static _button plyrcycle[4];
  int i = 0;
  int j = 0;
  
  if (drawfirst == 1)
  {
    back.init(10, 455, 100, 20, "Back");
    i = 0;
    while (i < 4)
    {
      if (player[i].playing == 1)
      {
        player[i].team = i + 1;
      }
      i++;
    }
    ok.init(545, 450, 95, 30, "OK");
    i = 0;
    while ((i < numplayers) && (i < 4) && (player[i].playing == 1))
    {  //that i < 4 is a precaution in case numplayers is somehow messed up
      j = i;
      while (j >= first_mission_character) j -= first_mission_character;  //in case playable characters < numplayers
      plyrcycle[i].init(180, 10 + (90 * i), 80, 80, "", character[j]->picture);
      player[i].number = j;
			currentcharacter[i] = character[j];
      opt[i].init(350, 40 + (90 * i), 80, 20, "Human");
      opt[i + 4].init(520, 30 + (90 * i), 40, 40, "", glb.bmp(13 + player[i].team));
      i++;
    }
    delay = 25;  //to keep a player from being accidentally clicked
    drawfirst = 0;
  }
  
  buffer_circlefill_gradient(595, 470, 130, GREY, BLACK);
  buffer_textout_ex(normal, "Controller", 360, 20, WHITE);
  buffer_textout_ex(normal, "Team", 525, 20, WHITE);
  list_players(numplayers);
  
  back.check();
  ok.check();
  i = 0;
  while (i < numplayers)
  {
    if (player[i].playing == 1)
    {
      opt[i].check();
      opt[i + 4].check();
      if (opt[i].clicked())
      {
        if (opt[i].get_text() == "Human")
        {
          opt[i].init(350, 40 + (90 * i), 80, 20, "AI");
        }
        else if (opt[i].get_text() == "AI")
        {
          opt[i].init(350, 40 + (90 * i), 80, 20, "Human");
        }
      }
      if (opt[i + 4].clicked())
      {
        player[i].team++;
        if (player[i].team > 4)
        {
          player[i].team = 1;
        }
        opt[i + 4].init(520, 30 + (90 * i), 40, 40, "", glb.bmp(13 + player[i].team));
      }
    }
    i++;
  }
  if (back.clicked())
  {
    drawfirst = 1;
    return MENU_LOAD;
  }
  if (ok.clicked())
  {
    drawfirst = 1;
    i = 0;
    while (i < 4)  //set whether players 3 and four are actually in the game
    {
      if (i < numplayers)
      {
        if (opt[i].get_text() == "Human")
        {
          player[i].controller = HUMAN;
        }
        else
        {
          player[i].controller = AI;
        }
      }
      i++;
    }
    pturn = 0;  //make player 1 start first
    global.loaded_game = 0;  //the game was not loaded from a saved file
    global.very_first_turn = 1;
    worldmap.scroll_x = 0;
    worldmap.scroll_y = 0;
    return MENU_INGAME_OPTIONS;
  }
  i = 0;
  while (i < 4)
  {
    if (player[i].playing == 1)
    {
      if (delay <= 0)
      {
        plyrcycle[i].check();
        if (plyrcycle[i].clicked())
        {
          player[i].number++;
          if (player[i].number >= first_mission_character) player[i].number -= first_mission_character;
					currentcharacter[i] = character[player[i].number];
          plyrcycle[i].init(180, 5 + (90 * i), 80, 80, "", currentcharacter[i]->picture);
        }
      }
      else
      {
        plyrcycle[i].draw();
        delay--;
      }
      if (plyrcycle[i].mouseover())
      {
        description(player[i].number, 320, 360);
      }
    }
    i++;
  }
  draw_mouse();
  return MENU_OPTIONS;
}

void description(int c, int x, int y)
{
  string n, m, s, w, p, d;
  if ((c > -1) && (c < signed(character.size())))
  {
    n = character[c]->getname();
    m = character[c]->getdescription();
    s = "Strength: ";
    s += describe_strength(character[c]->strength);
    w = "Weakness: ";
    w += describe_weakness(character[c]->weakness);
    p = "Power: ";
    p += character[c]->getpowername();
  }
  else
  {
    n = "";
    m = "";
    p = "";
  }
  buffer_textout_centre_ex(normal, n.c_str(), x, y, WHITE);
  buffer_textout_centre_ex(normal, m.c_str(), x, y + 11, WHITE);
  buffer_textout_centre_ex(normal, s.c_str(), x, y + 22, GREEN);
  buffer_textout_centre_ex(normal, w.c_str(), x, y + 33, RED);
  buffer_textout_centre_ex(normal, p.c_str(), x, y + 44, WHITE);
	display_powers(c, x - 120, y + 55, 15);
//  buffer_textout_centre_ex(normal, d.c_str(), x, y + 66, LGREY);
}

string describe_strength(int num)
{
  switch(num)
  {
    case 0:
      return "Direct Attacks";
      break;
    case 1:
      return "Ranged Attacks";
      break;
    case 2:
      return "Land Units";
      break;
    case 3:
      return "Air Units";
      break;
    case 4:
      return "Sea Units";
      break;
    case 5:
      return "None";
      break;
  }
  return "-ERROR-";
}

string describe_weakness(int num)
{  //the same as describe_strength(), but a different name makes things easier
  return describe_strength(num);
}

extern int player_color(int i);
void list_players(int numplayers)
{
  int i = 0;
  char m[15];
  while (i < numplayers)
  {
    sprintf(m, "Player %-1d", i + 1);
    buffer_rectfill_gradient(0, 25 + (90 * i), 155, 75 + (90 * i), player_color(i), BLACK, BLACK, player_color(i));
    buffer_textout_ex(big, m, 30, 36 + (90 * i), WHITE);
    i++;
  }
}

int do_gameload()
{
  int i, o, p, num, safety;
  int type, tilex, tiley, ammo, gas, ready, capturing, submerged, unum;
  float health;
  int thechoice = -1;
  int temp;
  char text[30] = "";
  char d[30];
  string mname;
  string ainame;
  static int first = 1;
  static _button choice[10];
  static _button delsave[9];
  char path[30];
  if (first == 1)
  {
    o = 0;
    while (o < 9)
    {
      sprintf(path, "saves/game%-1d.sav", o);
      if (exists(path) != 0)
			{
			  ifstream n(path);
        if (n.bad())
        {
          choice[o].init(210, 80 + (o * 35), 140, 20, "Empty");
        }
        else
        {
          n >> text;
          choice[o].init(210, 80 + (o * 35), 140, 20, text);
        }
				n.close();
			}
			else
			{
				choice[o].init(210, 80 + (o * 35), 140, 20, "Empty");
			}
      delsave[o].init(375, 82 + (o * 35), 80, 16, "Delete");
      o++;
    }
    choice[9].init(10, 455, 100, 20, "Back");
    gameoptions.reset();
    first = 0;
  }
  glb.draw(8, 0, 0);
  glb.draw(9, 0, 0);
  i = 0;
  while (i < 10)
  {
    choice[i].check();
    if ((choice[i].clicked()) && (choice[i].get_text() != "Empty"))
    {
      thechoice = i;
    }
    if (i < 9)
    {
      delsave[i].check();
      if (delsave[i].clicked())
      {  //if the delete option was chosen for this save file
        sprintf(path, "saves/game%-1d.sav", i);
        delete_file(path);
        choice[i].init(210, 80 + (i * 35), 140, 20, "Empty");
      }
    }
    i++;
  }
  if (((thechoice != -1) && (thechoice != 9)) || (key[KEY_Z]))  //Z = LAST DEBUG SAVE
  {
    if ((thechoice != -1) && (thechoice != 9))
    {
      sprintf(path, "saves/game%-1d.sav", thechoice);
    }
    else
    {
      sprintf(path, "saves/gamedebug.sav");
    }
    ifstream savefile(path);
    if (!(savefile.bad()))
    {
      worldmap.reset();
      savefile >> d >> worldmap.l >> worldmap.h;
      o = 0;
      while (o < worldmap.h)
      {
        p = 0;
        while (p < worldmap.l)
        {
          savefile >> temp;
          worldmap.tile[p][o].change_type(temp / 100, temp % 100);
          p++;
        }
        o++;
      }
      safety = 0;
      o = 0;
      while (o < 4)
      {
        player[o].clear_units();
        savefile >> d >> player[o].playing;
        savefile >> d >> player[o].everplaying;
        if (player[o].everplaying == 1)
        {
          savefile >> d >> player[o].number;
          savefile >> d >> player[o].cash;
          savefile >> d >> player[o].power;
          savefile >> d >> player[o].controller;
          savefile >> d >> player[o].powered;
          savefile >> d >> unum;
          savefile >> d >> player[o].team;
          savefile >> d >> player[o].tookturn;
          p = 0;
          while (p < unum)
          {
            savefile >> d >> type;
            savefile >> d >> tilex;
            savefile >> d >> tiley;
            savefile >> d >> health;
            savefile >> d >> ammo;
            savefile >> d >> gas;
            savefile >> d >> ready;
            savefile >> d >> capturing;
            savefile >> d >> submerged;
            num = player[o].create_unit(type, tilex, tiley, o);
            player[o].unit[num].health = health;
            player[o].unit[num].ammo = ammo;
            player[o].unit[num].gas = gas;
            player[o].unit[num].ready = ready;
            player[o].unit[num].capturing = capturing;
            player[o].unit[num].submerged = submerged;
            savefile >> d >> player[o].unit[num].load[0].loaded;
            savefile >> d >> player[o].unit[num].load[0].type;
            savefile >> d >> player[o].unit[num].load[0].health;
            savefile >> d >> player[o].unit[num].load[0].ammo;
            savefile >> d >> player[o].unit[num].load[0].gas;
            savefile >> d >> player[o].unit[num].load[0].subload.loaded;
            savefile >> d >> player[o].unit[num].load[0].subload.type;
            savefile >> d >> player[o].unit[num].load[0].subload.health;
            savefile >> d >> player[o].unit[num].load[0].subload.ammo;
            savefile >> d >> player[o].unit[num].load[0].subload.gas;
            savefile >> d >> player[o].unit[num].load[1].loaded;
            savefile >> d >> player[o].unit[num].load[1].type;
            savefile >> d >> player[o].unit[num].load[1].health;
            savefile >> d >> player[o].unit[num].load[1].ammo;
            savefile >> d >> player[o].unit[num].load[1].gas;
            savefile >> d >> player[o].unit[num].load[1].subload.loaded;
            savefile >> d >> player[o].unit[num].load[1].subload.type;
            savefile >> d >> player[o].unit[num].load[1].subload.health;
            savefile >> d >> player[o].unit[num].load[1].subload.ammo;
            savefile >> d >> player[o].unit[num].load[1].subload.gas;
            p++;
          }
        }
        o++;
      }
			load_saved_characters(path);
      savefile >> d >> pturn >> gameoptions.funding;
      savefile >> gameoptions.show_damage >> gameoptions.time >> loaded_time;
      getline(savefile, mname);  //this first one makes mname empty for some reason
      getline(savefile, mname);  //so I have to call it again to actually get the line
      worldmap.set_name(mname);
      load_ai(mname);
      global.loaded_game = 1;  //the game has been loaded from a file
      first = 1;
      get_connected_beaches();
			get_teleports();
      global.very_first_turn = 1;
      minimap.create();
      clear_particles();
      return LOGIC;
    }
  }
  else if (thechoice == 9)
  {
    first = 1;
    return MENU_FIRST;
  }
  draw_mouse();
  return MENU_GAME_LOAD;
}

void get_connected_beaches()
{
  int x, y;
  _loc d;
  _connectedlocs t;
  beaches.clear();
  beaches.reserve(5);
  y = 0;
  while (y < worldmap.h)
  {
    x = 0;
    while (x < worldmap.l)
    {
      if (is_beach(x, y) == 1)
      {
        if (beach_already_listed(x, y) == 0)
        {
          d.x = x;
          d.y = y;
          beaches.push_back(t);
          beaches[beaches.size() - 1].loc.reserve(10);
          beaches[beaches.size() - 1].loc.push_back(d);
          add_surrounding_beaches(beaches.size() - 1, x, y);
        }
      }
      x++;
    }
    y++;
  }
}

void add_surrounding_beaches(int bnum, int x, int y)
{
  _loc d;
  if (x - 1 > -1)
  {
    if (is_beach(x - 1, y) == 1)
    {
      if (beach_already_listed(x - 1, y) == 0)
      {
        d.x = x - 1;
        d.y = y;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x - 1, y);
      }
    }
  }
  if (x + 1 < worldmap.l)
  {
    if (is_beach(x + 1, y) == 1)
    {
      if (beach_already_listed(x + 1, y) == 0)
      {
        d.x = x + 1;
        d.y = y;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x + 1, y);
      }
    }
  }
  if (y - 1 > -1)
  {
    if (is_beach(x, y - 1) == 1)
    {
      if (beach_already_listed(x, y - 1) == 0)
      {
        d.x = x;
        d.y = y - 1;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x, y - 1);
      }
    }
  }
  if (y + 1 < worldmap.h)
  {
    if (is_beach(x, y + 1) == 1)
    {
      if (beach_already_listed(x, y + 1) == 0)
      {
        d.x = x;
        d.y = y + 1;
        beaches[bnum].loc.push_back(d);
        add_surrounding_beaches(bnum, x, y + 1);
      }
    }
  }  
}

int is_beach(int x, int y)
{
  if (worldmap.tile[x][y].get_set() == 3)
  {  //3 is the set for beaches (called shoals in mapedit)
    if (worldmap.tile[x][y].get_number() < 25)  //shoal tiles 25-28 are actually sea transitions
    {
      return 1;
    }
  }
  if (worldmap.tile[x][y].is_building(PORT))
  {
    return 1;
  }
  return 0;
}

int beach_already_listed(int x, int y)
{
  unsigned int i, j;
  _loc d;
  d.x = x;
  d.y = y;
  i = 0;
  while (i < beaches.size())
  {
    j = 0;
    while (j < beaches[i].loc.size())
    {
      if ((d.x == beaches[i].loc[j].x) && (d.y == beaches[i].loc[j].y))
      {
        return 1;
      }
      j++;
    }
    i++;
  }
  return 0;
}

void get_teleports()
{
	int i, j;
	_loc l;
	teleports.clear();
	
	j = 0;
	while (j < worldmap.h)
	{
		i = 0;
		while (i < worldmap.l)
		{
			if (worldmap.tile[i][j].same_type(6, 0))
			{
				l.x = i;
				l.y = j;
				teleports.push_back(l);
			}
			i++;
		}
		j++;
	}
}

void display_powers(int thechar, int x, int y, int iconsperrow)
{
	int i = 0, currow = 0, curcol = 0, p;
	
	while (i < NUM_POWERS)
	{
		p = character[thechar]->power[i];
		while (p > 0)
		{
			glb.draw(21 + i, x + curcol * 20, y + currow * 20);
			curcol++;
			if (curcol >= iconsperrow)
			{
				curcol = 0;
				currow++;
			}
			p--;
		}
		i++;
	}
}
