#include "Rules.h"

Rules::Rules ()
{
  clear();
}

Rules::~Rules ()
{
  clear();
}

//this initializes EVERYTHING.
void Rules::clear()
{
  clearPlayerAttacksRound();
  clearPlayerDefenseRound();
}

void Rules::clearPlayerAttacksRound()
{
  playerAttackPaths.clear();
}

void Rules::clearPlayerDefenseRound()
{
  playerDefenseArray.clear();
}

//statehandler calls this function. Rules checks itself to make sure it has started what it needs to run properly.
void Rules::startState (int state)
{
  bool startedBattle=false;
  session->getBool("Started Battle", startedBattle);

  //make sure battle has been initiated.
  switch (state)
    {
    case(STATE_ATTACK_PREVIEW):
    case(STATE_ATTACK_DRAWING):
    case(STATE_ATTACK_FINISHED):
    case(STATE_ATTACK_WAIT_FOR_USER):
    case(STATE_DEFEND_CLICKING):
      if (!startedBattle)
        {
	  //setup player
	  player1.clear(PLAYER_CLASS_WARRIOR);

          //load all the rules required to start a battle.
	  player1.learnPlayerAbility("Wait");
	  player1.learnPlayerAbility("AwesomeAbility");

	  player1.readyAbility("AwesomeAbility", 4);
	  player1.readyAbility("Wait", 9);

	  //get new attack paths
	  vector <string> attackPathNames;
	  player1.getAttackPathNames(attackPathNames);

	  //load attack paths
	  int i;
	  for (i=0; i<int(attackPathNames.size()); i++)
	    {
	      addAttackPath(attackPathNames[i]);
	    }

	  //Set player's health to maximum.
	  player1.setCurrentHealth(player1.getHealth());
        }
      break;
    };
}

//sets and gets Session
void Rules::setSession (Session * ses)
{
  session = ses;
}

Session * Rules::getSession ()
{
  return session;
}

//AttackPattern
vector<HitBox*> & Rules::getAttackPatternPoints()
{
  return attackPatternPoints;
}

vector<int> & Rules::getAttackPatternSegments()
{
  return attackPatternSegments;
}

vector<int> & Rules::getAttackPatternPointer()
{
  return attackPatternPointer;
}

//populates a text listing for the information shown to the user for the selected attack.
void Rules::updatePowerPreviewText (vector<FormattedText>& attackPreviewText)
{
  attackPreviewText.clear();
  FormattedText temp;
  bool validAttackPath;
  map<string, PlayerAbility>::iterator playerAbility;
  int slot=session->getPowerSelector()->getSelected();

  //First line: The name of the power and its recharge/uses remaining.
  temp.clear();
  validAttackPath=getPlayerAbility(playerAbility, slot);

  if (!validAttackPath)
    {
      temp.setText("This isn't an attack.");
      attackPreviewText.push_back(temp);
    }
  else
    {
      //first line is the name of the ability followed by the recharge or time remaining.
      temp.setText(playerAbility->second.getAbilityName());
      //append waiting time or amount here.
      temp.setNewline(true);
      attackPreviewText.push_back(temp);

      temp.clear();
      temp.setText(playerAbility->second.getDescription());
      attackPreviewText.push_back(temp);
      //third line is difficulty in drawing it
      //fourth line is number of allowed misses/no damage warning
    }
}

//make a DefenseArray.
void Rules::addDefenseArray(const string & name)
{
  //STUBS aplenty for these settings.

  //needs dimensions and moving left from config
  playerDefenseArray.clear();
  playerDefenseArray.setMovingLeft(true);
  playerDefenseArray.setWindowWidth(320);
  playerDefenseArray.setWindowHeight(250);

  //needs parry width and travel speed based on ruleset's stats
  playerDefenseArray.setParryWindowWidth(300);
  playerDefenseArray.setTravelSpeed(FixedInt(1));

  //load hash's attributes for each point
  prepareAndAddDefensePoint(name);
}

DefenseArray & Rules::getDefenseArray()
{
  return playerDefenseArray;
}

//when the user clicks on a path, check to see if it should halt all points.
//return true if so.
//indx stores the indecies of all the defense points on screen.
bool Rules::checkForCriticalDefense (vector<int>& indx)
{
  int index;

  //STUB: Right now it's a fixed chance. It should depend on the player's stats.
  if (generateRandomNumber(3)==0)
    {
      for (index=0; index<int(indx.size()); index++)
        getDefenseArray().startReversingDefensePoint(indx[index], DEFENSE_POINT_STOP);
      return true;
    }
  else
    return false;
}

//During a defense round, a point escaped. Remove it from the current player's battle armor.
bool Rules::defensePointEscaped(int damage)
{
  //need to interact with PlayerDuringBattle
  return true;
}

//Returns true if the player's battle armor is negative.
bool Rules::playerFailedDefense()
{
  //need to interact with PlayerDuringBattle
  return true;
}

//returns the number of defense points that remain.
int Rules::getNumberOfDefensePoints()
{
  return getDefenseArray().getNumberOfDefensePoints();
}

bool Rules::getPlayerAbility(map<string, PlayerAbility>::iterator & ans, int slot)
{
  return player1.getPlayerAbility(ans, slot);
}

//makes an attack path
bool Rules::getAttackPath(map<string, AttackPath>::iterator & ans)
{
  int slot = session->getPowerSelector()->getSelected();
  map <string, PlayerAbility> :: iterator pa;
  bool validData = getPlayerAbility(pa, slot);

  if (!validData)
    return false;

  ans=playerAttackPaths.find(pa->second.getAttackPath());

  return (ans!=playerAttackPaths.end() && ans->second.isValid());
}

//populates vector with the graphic resource names of the button icons.
void Rules::getButtonIcons (vector<string> & str)
{
  str.clear();
  map <string, PlayerAbility> :: iterator pa;
 //go through player's attack paths
  for (int i=0; i < 10; i++)
    {
      if (getPlayerAbility(pa, i))
        str.push_back(pa->second.getButtonIcon());
      else
        str.push_back("NULL_INDEX");
    }
}

//return the player
Player * Rules::getPlayer()
{
  return &player1;
}
