#ifndef GAMESTATE_H
#define GAMESTATE_H

#include "Input.h"
#include "SDL.h"
#include "LocalInput.h"
#include "Command.h"

#include "../ruleset/Ruleset.h"
#include "../ruleset/Player.h"


#include "../graphics/Renderer.h"
#include "../graphics/shippingHandler.h"

#include "../interface/PowerSelector.h"
#include "../interface/Button.h"
#include "../interface/ListBox.h"
#include "../interface/HelpBox.h"
#include "../interface/FormattedText.h"
#include "../interface/TextFeeder.h"

#include "../util/fileUtils.h"
#include "../util/mathUtils.h"

#include <libxml/parser.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#include <stdint.h>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;

//game states
#define GAMESTATE_INITIAL 0
#define GAMESTATE_QUIT 1
#define GAMESTATE_MAIN_MENU 2
#define GAMESTATE_MAP 3
#define GAMESTATE_BATTLE_SWOOSH 4
#define GAMESTATE_CREDITS 5
#define GAMESTATE_INVENTORY 6
#define GAMESTATE_GAME_MENU 7
#define GAMESTATE_NEW_GAME 8
#define GAMESTATE_CHOOSE_YOUR_CHARACTER 9
#define GAMESTATE_CHOOSE_YOUR_INTRO_POWERS 10
#define GAMESTATE_CONTINUE_GAME 11
#define GAMESTATE_SAVE 12
#define GAMESTATE_BATTLE_CHECK_FOR_RESULT 14
#define GAMESTATE_BATTLE_PLAYER_PHASE 15
#define GAMESTATE_BATTLE_ENEMY_PHASE 16
#define GAMESTATE_BATTLE_SHOW_REWARDS 17
#define GAMESTATE_BATTLE_GAME_OVER 18
#define GAMESTATE_ABILITY 19
#define GAMESTATE_LEVEL_COMPLETE 20
#define GAMESTATE_LEVEL_NEW 21

class GameState {
 public:
  GameState ();
  ~GameState ();
  bool initialize ();
  uint8_t getGameState ();
  void gatherInput ();

  void applyRuleToRuleset (); //if it makes a command
  void applyCommandToProgram (); //if it's quit/expand window etc.
  void go ();

  void gamestateInitial ();
  void gamestateInitialStartup ();

  void gamestateQuit ();

  void gamestateMainMenuStartup();
  void gamestateMainMenuAfterDraw(uint8_t);

  void gamestateMapStartup(vector <MapUnit> &, MapUnit &);
  void gamestateMapAfterDraw(uint8_t);

  void gamestateBattleSwooshStartup ();
  void gamestateBattleSwooshBeforeDraw ();
  void gamestateBattleSwooshAfterDraw ();

  void gamestateBattleCheckForResultAfterDraw ();

  void gamestateBattlePlayerPhaseAfterDraw (uint8_t);
  void preparePowerPreview(int selectedPower);

  void gamestateBattleEnemyPhaseAfterDraw (uint8_t);

  void gamestateBattleShowRewardsStartup ();
  void gamestateBattleShowRewardsAfterDraw (uint8_t);

  void gamestateBattleGameOverAfterDraw (uint8_t);

  void gamestateCreditsAfterDraw(uint8_t);

  void gamestateInventoryAfterDraw(uint8_t);

  void gamestateGameMenuAfterDraw(uint8_t);

  void gamestateNewGameAfterDraw(uint8_t);

  void gamestateChooseYourCharacterAfterDraw(uint8_t);

  void gamestateChooseYourIntroPowersStartup();
  void gamestateChooseYourIntroPowersAfterDraw(uint8_t);

  void gamestateContinueGameAfterDraw(uint8_t);

  void gamestateSaveAfterDraw();

  void gamestateAbilityAfterDraw(uint8_t, uint8_t);

  void gamestateLevelCompleteAfterDraw();

  void gamestateLevelNewAfterDraw();

  void setNewGameState (uint8_t );
  void addQuitCommand ();

  void helpStackBeforeDraw ();
  void helpStackHandleInput ();

  bool loadHelpText(HelpBox & hb, const string & ref);
  bool loadSingleFormattedText (xmlDocPtr doc, xmlXPathContextPtr xpathCtx, const string & xpath, HelpBox & hb);
  void checkInputOnHelpBox(HelpBox & hb, int mouseX, int mouseY, int mouseButt);
  uint8_t checkInputOnListBox (ListBox & lb, vector<string>& stringList, vector<string>& helpRefList, int mouseX, int mouseY, int mouseButt);

  void stateStartup();
  void stateBeforeDrawing(bool &);
  void stateAfterDrawing();
  void stateShutdown();
 private:
  uint8_t currentGamestate, previousGamestate;
  bool firstTimeInNewState;

  uint32_t startTime;

  shippingHandler * sdlRE;
  LocalInput * player1Input;
  vector <Input> inputBuffer;
  vector <Input> :: iterator inputBufferIterator;
  vector <Command *> * commandBuffer;

  Ruleset rulez;

  string helpReference;
  bool newHelpReference;

  //output
 private:
  uint32_t lastFrame;

  string font1Index, font2Index;
  string stringOutput0;

  Renderer rander;
 public:
  void clearButtons (uint8_t num = 0);
  void buttonUpdateClickStatus (Input &, uint8_t num = 0);
  void listBoxUpdateClickStatus (Input &, uint8_t num = 0);
  int checkInputOnPowerSelector(PowerSelector & ps, int mouseX, int mouseY);
  int updateSelectedPower(PowerSelector & ps, Input & comm, string & helpRef);

  void screenDelay ();

  bool isMouseOnHotSpot(Input &, Button & b, bool respectCamera);

  //interface
 private:
  vector <Button> buttonVect;
  vector <string *> stringVect;
  vector <string> stringVect2;

  uint8_t numButtons;
  vector <HelpBox> helpBoxVect;

  vector <ListBox> listBoxVect;
  uint8_t numListBoxes;

  PowerSelector playerPowerSelector;

  vector<TextFeeder> textFeeders;
 public:
  void storeLevelUp ();
 private:
  vector <uint8_t> levelUps;

 public:
  vector <string> tempStr;
  vector <string> tempHelpStr;
  vector <bool> tempBool;
};

#endif
