#include "StateHandler.h"

StateHandler::StateHandler ()
{
  session=NULL;
}

StateHandler::~StateHandler ()
{
  session->getRenderer()->endStateReleaseResources(STATE_INITIALIZE);
  xmlCleanupParser();
}

//This is the main processing loop.
void StateHandler::go()
{
  int currentState=STATE_INITIALIZE, newState=STATE_NONE;
  session->getInt("Current State", currentState);

  //before you draw to screen, clear it then tell the state to prepare to draw.
  session->getShippingHandler() -> clearScreen ();
  dispatchState (currentState, BEFORE_DRAW_STATE);
  //tell the renderer to draw to screen.
  session->getRenderer()->drawState(currentState);
  session->getShippingHandler() -> flipScreen ();
  //now, gather input and apply it to the screen
  gatherInput ();
  dispatchState (currentState, APPLY_INPUT_STATE);
  //delay game to keep frame rate at 30 fps
  session->getRenderer()->screenDelay();
  //check for a quit command.
  checkForQuitInput();
  //check for a state change
  session->getParamNew()->getInt("New State", newState);
  if (newState != STATE_NONE)
    {
      //if there is a new state:
      session->setInt("Previous State", currentState);
      //end the previous state
      dispatchState (currentState, END_STATE);
      //Overwrite the currentState
      session->setInt("Current State", newState);
      currentState=newState;

      //Swap params
      session->swapParams();
      //clear the new state
      session->getParamNew()->setInt("New State", STATE_NONE);
      //run startup for the new state
      dispatchState (currentState, START_STATE);
    }

  //cleanup: clear inputs
  session->getPlayerInput().getInputs().clear();
}

bool StateHandler::initialize ()
{
  initializeAngles();
  seedRandomization();

  //setting up param swap.
  session->initParams();

  //start the shippingHandler, tell it to set up graphics.
  SDL_ClearError ();

  if (session->getShippingHandler()->Startup () == false)
    {
      writeToErrorLog ("SDL Startup Failed: ", 0);
      writeToErrorLog (SDL_GetError (), 1);
      return false;
    }

  //Clear the player's inputs.
  session->getPlayerInput().getInputs().clear();
  //Tell renderer to load basic graphics
  session->getRenderer()->startStateLoadResources(STATE_INITIALIZE);

  //DEBUG
  debugTest(1);

  session->setBool("Wants to Quit", false);
  session->setInt("Last Frame Tick", 0);
  session->getParamNew()->setInt("New State", STATE_ATTACK_PREVIEW);
  session->setInt("Current State", STATE_INITIALIZE);
  return true;
}

void StateHandler::quit()
{
  //Tell renderer to release basic graphics
  session->getRenderer()->endStateReleaseResources(STATE_INITIALIZE);
}

//polls devices and stores input in them.
void StateHandler::gatherInput ()
{
  SDL_Event mainEvent;
  while (SDL_PollEvent (&mainEvent)){
    switch (mainEvent.type)
      {
      case (SDL_KEYUP):
      case (SDL_KEYDOWN):
      case (SDL_MOUSEMOTION):
      case (SDL_MOUSEBUTTONUP):
      case (SDL_MOUSEBUTTONDOWN):
        session->getPlayerInput().pollInput(mainEvent);
        break;
      default:
        break;
      };
  }
}

bool StateHandler::getWantsToQuit()
{
  bool ans = false;
  session->getBool("Wants to Quit", ans);
  return ans;
}

bool StateHandler::checkForQuitInput()
{
  vector <Input> :: iterator inputIter=session->getPlayerInput().getInputs().begin();

  while (inputIter!=session->getPlayerInput().getInputs().end())
    {
      if (inputIter->getInput()==INPUT_QUIT)
        {
          session->setBool("Wants to Quit", true);
          return true;
        }
      inputIter++;
    }
  return false;
}

//State control: The methods used to select state routines
//break according to target state and type of call.
void StateHandler::dispatchState (int targetState, int partOfState)
{
  if (partOfState==START_STATE)
    session->getRules()->startState(targetState);

  switch(targetState)
    {
    case(STATE_PLAYER_ATTACKS):
      if (partOfState==START_STATE)
        stateStartPlayerAttacks ();
      else if (partOfState==BEFORE_DRAW_STATE)
        stateBeforeDrawPlayerAttacks ();
      else if (partOfState==APPLY_INPUT_STATE)
        stateApplyInputPlayerAttacks ();
      else
        stateEndPlayerAttacks ();
      break;
    case(STATE_BATTLE_SWITCH_ROUND):
      if (partOfState==START_STATE)
        stateStartBattleSwitchRound ();
      else if (partOfState==BEFORE_DRAW_STATE)
        stateBeforeDrawBattleSwitchRound ();
      else if (partOfState==APPLY_INPUT_STATE)
        stateApplyInputBattleSwitchRound ();
      else
        stateEndBattleSwitchRound ();
      break;
    case(STATE_ATTACK_PREVIEW):
      if (partOfState==START_STATE)
        stateStartAttackPreview ();
      else if (partOfState==BEFORE_DRAW_STATE)
        stateBeforeDrawAttackPreview ();
      else if (partOfState==APPLY_INPUT_STATE)
        stateApplyInputAttackPreview ();
      else
        stateEndAttackPreview ();
      break;
    case(STATE_ATTACK_DRAWING):
      if (partOfState==START_STATE)
        stateStartAttackDrawing ();
      else if (partOfState==BEFORE_DRAW_STATE)
        stateBeforeDrawAttackDrawing ();
      else if (partOfState==APPLY_INPUT_STATE)
        stateApplyInputAttackDrawing ();
      else
        stateEndAttackDrawing();
      break;
    case(STATE_ATTACK_WAIT_FOR_USER):
      if (partOfState==START_STATE)
        stateStartAttackWaitForUser ();
      else if (partOfState==BEFORE_DRAW_STATE)
        stateBeforeDrawAttackWaitForUser ();
      else if (partOfState==APPLY_INPUT_STATE)
        stateApplyInputAttackWaitForUser ();
      else
        stateEndAttackWaitForUser();
      break;
    case(STATE_DEFEND_CLICKING):
      if (partOfState==START_STATE)
        stateStartDefendClicking ();
      else if (partOfState==BEFORE_DRAW_STATE)
        stateBeforeDrawDefendClicking ();
      else if (partOfState==APPLY_INPUT_STATE)
        stateApplyInputDefendClicking ();
      else
        stateEndDefendClicking ();
      break;
    default:
      break;
    };

  if (partOfState==START_STATE)
    session->getRenderer()->startStateLoadResources(targetState);


  //make sure battle has been initiated.
  switch (targetState)
    {
    case(STATE_ATTACK_PREVIEW):
    case(STATE_ATTACK_DRAWING):
    case(STATE_ATTACK_FINISHED):
    case(STATE_ATTACK_WAIT_FOR_USER):
    case(STATE_DEFEND_CLICKING):
      session->setBool("Started Battle", true);
      break;
    };
}

//debug testing
void StateHandler::debugTest(int test)
{
  switch (test)
    {
    case(0):
      stateDebugBattleSwitchRound ();
      break;
    case(1):
      stateDebugAttackPreview ();
      break;
    default:
      break;
    };
}

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

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

//goes through all of the inputs and all of the hitBoxes, applying if the type of input you are looking is there.
void StateHandler::applyInputToHitBoxes (int inputToLookFor)
{
  vector<Input>::iterator inputIter=session->getPlayerInput().getInputs().begin(),
    inputEnd=session->getPlayerInput().getInputs().end();
  vector<HitBox>::iterator hitBoxIter=session->getHitBoxes().begin(),
    hitBoxEnd=session->getHitBoxes().end();

  //first clear all the hitBox statuses
  while (hitBoxIter!=hitBoxEnd)
    {
      hitBoxIter->clearWasHit();
      hitBoxIter++;
    }
  //now look for inputs that match the type we're looking for
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==uint32_t(inputToLookFor))
        {
          hitBoxIter=session->getHitBoxes().begin();
          //apply input to all hitBoxes
          while (hitBoxIter!=hitBoxEnd)
            {
              hitBoxIter->wasHitBoxHit(inputIter->getData()[0],inputIter->getData()[1],inputIter->getData()[2]);
              hitBoxIter++;
            }
        }
      inputIter++;
    }
}

//This uses a given vector of hitboxes to check.
void StateHandler::applyInputToHitBoxes (int inputToLookFor, vector <HitBox*> & hbs)
{
  vector<Input>::iterator inputIter=session->getPlayerInput().getInputs().begin(),
    inputEnd=session->getPlayerInput().getInputs().end();
  vector<HitBox*>::iterator hitBoxIter=hbs.begin(),
    hitBoxEnd=hbs.end();

  //first clear all the hitBox statuses
  while (hitBoxIter!=hitBoxEnd)
    {
      (*hitBoxIter)->clearWasHit();
      hitBoxIter++;
    }
  //now look for inputs that match the type we're looking for
  while (inputIter!=inputEnd)
    {
      if (int(inputIter->getInput())==inputToLookFor)
        {
          hitBoxIter=hbs.begin();
          //apply input to all hitBoxes
          while (hitBoxIter!=hitBoxEnd)
            {
              (*hitBoxIter)->wasHitBoxHit(inputIter->getData()[0],inputIter->getData()[1],inputIter->getData()[2]);
              hitBoxIter++;
            }
        }
      inputIter++;
    }
}

/////////////////////////////////////////////////////////
///Specific phases are below

//Player Attacks Phase
void StateHandler::stateDebugPlayerAttacks ()
{
  session->getParamNew()->setInt("New State", STATE_PLAYER_ATTACKS);
  dispatchState (STATE_BATTLE_SWITCH_ROUND, START_STATE);
}

void StateHandler::stateStartPlayerAttacks ()
{
  session->getRenderer()->stateStartPlayerAttacks();
}

void StateHandler::stateBeforeDrawPlayerAttacks ()
{
}

void StateHandler::stateApplyInputPlayerAttacks ()
{
}

void StateHandler::stateEndPlayerAttacks ()
{
}

//Round switching phase
void StateHandler::stateDebugBattleSwitchRound ()
{
  //pretend the mouse clicked somewhere.
  session->getParamNew()->setBool("Mouse Hit", true);
  session->getParamNew()->setInt("X Pos", 100+10);
  session->getParamNew()->setInt("Y Pos", 100+20);
  session->getParamNew()->setInt("Button", 1);
  session->getParamNew()->setInt("New State", STATE_BATTLE_SWITCH_ROUND);

  dispatchState (STATE_BATTLE_SWITCH_ROUND, START_STATE);
}

void StateHandler::stateStartBattleSwitchRound ()
{
  session->getParamNew()->setInt("Start Time", SDL_GetTicks());
}

void StateHandler::stateBeforeDrawBattleSwitchRound ()
{
}

void StateHandler::stateApplyInputBattleSwitchRound ()
{
  int phaseStartTime=0, previousState;
  session->getParamNew()->getInt("Start Time", phaseStartTime);
  session->getInt("Previous State", previousState);
  if (SDL_GetTicks()-phaseStartTime > 2000)
    {
      //determine if the player won
      if (false)
	{
	}
      //determine if the player lost
      else if (false)
	{
	}
      //Change state based on the previous state
      else if (previousState == STATE_ATTACK_DRAWING || 
	       previousState == STATE_ATTACK_PREVIEW ||
	       previousState == STATE_ATTACK_FINISHED)
	session->getParamNew()->setInt("New State", STATE_DEFEND_CLICKING);
      else if (previousState == STATE_DEFEND_CLICKING)
	session->getParamNew()->setInt("New State", STATE_ATTACK_PREVIEW);
    }
}

void StateHandler::stateEndBattleSwitchRound ()
{
}

//Feature Testing phase
void StateHandler::stateDebugTest ()
{
}

void StateHandler::stateStartTest ()
{
  session->getRenderer()->stateStartTest();
}

void StateHandler::stateBeforeDrawTest ()
{
}

void StateHandler::stateApplyInputTest ()
{
}

void StateHandler::stateEndTest ()
{
}

//Attack Preview shows the attack the player wants to use.
void StateHandler::stateDebugAttackPreview ()
{
  session->setInt("Battle Clickzone X", 320);
  session->setInt("Battle Clickzone Y", 70+125);
}

void StateHandler::stateStartAttackPreview ()
{
  session->getRenderer()->stateStartAttackPreview(0);
}

void StateHandler::stateBeforeDrawAttackPreview ()
{
}

void StateHandler::stateApplyInputAttackPreview ()
{
  //Change state if the user clicks on the first point on the attack path.
  vector<HitBox>::iterator firstPoint;
  vector<Input>::iterator inputIter, inputEnd;
  map<string, AttackPath>::iterator attackPath;

  inputIter=session->getPlayerInput().getInputs().begin();
  inputEnd=session->getPlayerInput().getInputs().end();
  //now look for inputs that match the type we're looking for
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN||inputIter->getInput()==INPUT_MOUSEUP||inputIter->getInput()==INPUT_MOUSEMOTION)
	{
	  session->getParamNew()->setInt("Test Mouse X", inputIter->getData()[0]);
	  session->getParamNew()->setInt("Test Mouse Y", inputIter->getData()[1]);
	}
      inputIter++;
    }
  if (session->getPowerSelector()->getSelected()!=-1 && session->getRules()->getAttackPath(attackPath))
    {
      firstPoint=attackPath->second.getFirstPoint();
      firstPoint->clearWasHit();

      inputIter=session->getPlayerInput().getInputs().begin();
      inputEnd=session->getPlayerInput().getInputs().end();
      //now look for inputs that match the type we're looking for
      while (inputIter!=inputEnd)
        {
          if (inputIter->getInput()==INPUT_MOUSEDOWN)
            {
              firstPoint->wasHitBoxHit(inputIter->getData()[0],inputIter->getData()[1],inputIter->getData()[2]);
              session->getParamNew()->setInt("Last Known Location X", inputIter->getData()[0]);
              session->getParamNew()->setInt("Last Known Location Y", inputIter->getData()[1]);
            }
          inputIter++;
        }

      if (firstPoint->getWasHit())
        session->getParamNew()->setInt("New State", STATE_ATTACK_DRAWING);
    }

  //now check on the power selector.
  inputIter=session->getPlayerInput().getInputs().begin();
  inputEnd=session->getPlayerInput().getInputs().end();
  int possibleSelectedCandidate;

  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN)
        {
          possibleSelectedCandidate=session->getPowerSelector()->mouseClickUpdate (inputIter->getData()[0],inputIter->getData()[1],inputIter->getData()[2]);
          if (possibleSelectedCandidate!=-1)
            {
              //The PowerSelector will highlight that power.
              session->getPowerSelector()->setSelected(possibleSelectedCandidate);

              //If you can use that power right now, update the power preview.
              session->getRenderer()->stateStartAttackPreview(1);
            }
        }
      inputIter++;
    }
}

void StateHandler::stateEndAttackPreview ()
{
}

//Attack Drawing, the player draws lines
void StateHandler::stateDebugAttackDrawing ()
{
}

void StateHandler::stateStartAttackDrawing ()
{
  session->getRenderer()->stateStartAttackDrawing();
  session->passOldHashToNewInt("Last Known Location X");
  session->passOldHashToNewInt("Last Known Location Y");

  session->setInt("Attack Drawing Start Time", SDL_GetTicks());
}

void StateHandler::stateBeforeDrawAttackDrawing ()
{
}

//The plan here is to determine the new state based on the mouse position and button status:
//1) If there are 2 points, bail to show results
//2) If the mouse has been released, go to ATTACK_WAIT_FOR_USER
//3) If the mouse travels through the second point, increment the segment and re-enter ATTACK_DRAWING
//4) If the mouse is not in the first point or it is outside the segment connecting the two points, go to ATTACK_WAIT_FOR_USER
//The last known mouse position is available at all times.
void StateHandler::stateApplyInputAttackDrawing ()
{
  vector<Input>::iterator inputIter;
  vector<Input>::iterator inputEnd=session->getPlayerInput().getInputs().end();
  int cx, cy, startTime;
  bool useLastKnownLocation=true, clickedInCorrectSpot;

  session->getInt("Attack Drawing Start Time", startTime);

  //If less than 2 points remaining then we're done. Go straight to results.
  if (session->getRules()->getAttackPatternPoints().size()<2)
    {
      session->getParamNew()->setInt("New State", STATE_BATTLE_SWITCH_ROUND);
      return;
    }

  //If there is a mouse up the user released the mouse and fails.
  inputIter=session->getPlayerInput().getInputs().begin();
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEUP)
        {
          //in case of failure, increment the segment and wait for the user.
          stateAttackDrawingHelper1(STATE_ATTACK_WAIT_FOR_USER);
          return;
        }
      inputIter++;
    }

  //If the mouse is dragged through the second point...
  HitBox * secondPoint = session->getRules()->getAttackPatternPoints()[1];
  useLastKnownLocation=true; clickedInCorrectSpot=false;
  secondPoint->clearWasHit();
  inputIter=session->getPlayerInput().getInputs().begin();
  map<string, AttackPath>::iterator attackPath;
  bool validPath = session->getRules()->getAttackPath(attackPath);
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN||INPUT_MOUSEMOTION||INPUT_MOUSEDRAG)
        {
          useLastKnownLocation=false;
          session->getParamNew()->setInt("Last Known Location X", inputIter->getData()[0]);
          session->getParamNew()->setInt("Last Known Location Y", inputIter->getData()[1]);
          if (!validPath || pointCircleCollision(inputIter->getData()[0],inputIter->getData()[1],
                                                 secondPoint->getPosX(), secondPoint->getPosY(),
                                                 attackPath->second.getCurrentRadius(SDL_GetTicks()-startTime)))
            clickedInCorrectSpot=true;
        }
      inputIter++;
    }
  if (useLastKnownLocation)
    {
      session->getParamNew()->getInt("Last Known Location X", cx);
      session->getParamNew()->getInt("Last Known Location Y", cy);
      if (!validPath || pointCircleCollision(cx, cy,
                                             secondPoint->getPosX(), secondPoint->getPosY(),
                                             attackPath->second.getCurrentRadius(SDL_GetTicks()-startTime)))
        clickedInCorrectSpot=true;
    }

  //...increment the segment to draw and reenter this state.
  if (clickedInCorrectSpot)
    {
      stateAttackDrawingHelper1(STATE_ATTACK_DRAWING);
      return;
    }

  //Now we need to check to see if the mouse is out of range. We already covered the endpoint, so now let's handle the startpoint and the rectangular segment connecting them.
  //First, the startpoint.

  HitBox * firstPoint = session->getRules()->getAttackPatternPoints()[0];
  useLastKnownLocation=true; clickedInCorrectSpot=false;
  firstPoint->clearWasHit();
  inputIter=session->getPlayerInput().getInputs().begin();
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN||INPUT_MOUSEMOTION||INPUT_MOUSEDRAG)
        {
          useLastKnownLocation=false;
          if (pointCircleCollision(inputIter->getData()[0],inputIter->getData()[1],
                                   firstPoint->getPosX(), firstPoint->getPosY(),
                                   attackPath->second.getCurrentRadius(SDL_GetTicks()-startTime)))
            clickedInCorrectSpot=true;
        }
      inputIter++;
    }

  if (useLastKnownLocation)
    {
      session->getParamNew()->getInt("Last Known Location X", cx);
      session->getParamNew()->getInt("Last Known Location Y", cy);

      if (pointCircleCollision(cx,cy,
                               firstPoint->getPosX(), firstPoint->getPosY(),
                               attackPath->second.getCurrentRadius(SDL_GetTicks()-startTime)))
        clickedInCorrectSpot=true;
    }

  if (clickedInCorrectSpot)
    return;

  //Now, check the segment between them.
  FixedInt corigx, corigy;
  AffineTransformationMatrix projectionMatrix;
  int abQuad;
  int ax=firstPoint->getPosX(), ay=firstPoint->getPosY(), bx=secondPoint->getPosX(), by=secondPoint->getPosY();

  //mathUtils does the heavy lifting here
  pointAnyRectangleCollisionHelper2 (ax, ay, bx, by, projectionMatrix, abQuad);

  useLastKnownLocation=true;

  inputIter=session->getPlayerInput().getInputs().begin();
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN||INPUT_MOUSEMOTION||INPUT_MOUSEDRAG)
        {
          useLastKnownLocation=false;
          session->getParamNew()->setInt("Last Known Location X", inputIter->getData()[0]);
          session->getParamNew()->setInt("Last Known Location Y", inputIter->getData()[1]);

          corigx=FixedInt(inputIter->getData()[0]);corigy=FixedInt(inputIter->getData()[1]);

          if (validPath && !pointAnyRectangleCollisionHelper1 (corigx, corigy, projectionMatrix,
                                                               attackPath->second.getCurrentRadius(SDL_GetTicks()-startTime),
                                                               ax, ay, bx, by, abQuad))
            {
              inputIter++;
              continue;
            }
          else
            return;
        }
      inputIter++;
    }

  //if there were no new locations, use the last known ones
  if (useLastKnownLocation)
    {
      session->getParamNew()->getInt("Last Known Location X", cx);
      session->getParamNew()->getInt("Last Known Location Y", cy);

      corigx=FixedInt(cx);corigy=FixedInt(cy);

      if (!validPath || pointAnyRectangleCollisionHelper1 (corigx, corigy, projectionMatrix,
                                                           attackPath->second.getCurrentRadius(SDL_GetTicks()-startTime),
                                                           ax, ay, bx, by, abQuad))
        return;
    }

  //OK, the mouse is not in the segment. Fail.
  stateAttackDrawingHelper1(STATE_ATTACK_WAIT_FOR_USER);
}

//increment the segment to draw and go to AttackDrawing.
//If there aren't enough segments remaining, goto show results.
void StateHandler::stateAttackDrawingHelper1(int altState)
{
  int segmentPartToDraw=0;
  session->getParamOld()->getInt("Segment Part to Draw", segmentPartToDraw);

  segmentPartToDraw++;
  session->getParamNew()->setInt("Segment Part to Draw", segmentPartToDraw);

  map<string, AttackPath>::iterator attackPath;
  bool validPath = session->getRules()->getAttackPath(attackPath);

  if (!validPath || segmentPartToDraw >= attackPath->second.getNumberOfPoints()-1)
    session->getParamNew()->setInt("New State", STATE_BATTLE_SWITCH_ROUND);
  else
    session->getParamNew()->setInt("New State", altState);
}

void StateHandler::stateEndAttackDrawing ()
{
  session->setInt("Attack Drawing Start Time", SDL_GetTicks());
}

//Attack Wait For User, user missed, waiting for user to click again
void StateHandler::stateDebugAttackWaitForUser ()
{
}

void StateHandler::stateStartAttackWaitForUser ()
{
  session->getRenderer()->stateStartAttackWaitForUser();
}

void StateHandler::stateBeforeDrawAttackWaitForUser ()
{
}

void StateHandler::stateApplyInputAttackWaitForUser ()
{
  //continue if the user clicks on the point.

  vector<Input>::iterator inputIter;
  vector<Input>::iterator inputEnd=session->getPlayerInput().getInputs().end();

  //If the mouse is dragged through the second point...
  HitBox * onlyPoint = session->getRules()->getAttackPatternPoints()[1];
  onlyPoint->clearWasHit();
  inputIter=session->getPlayerInput().getInputs().begin();
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN)
        {
          onlyPoint->wasHitBoxHit(inputIter->getData()[0],inputIter->getData()[1],inputIter->getData()[2]);
          session->getParamNew()->setInt("Last Known Location X", inputIter->getData()[0]);
          session->getParamNew()->setInt("Last Known Location Y", inputIter->getData()[1]);
        }
      inputIter++;
    }

  int segmentPartToDraw=0;

  //...increment the segment to draw and reenter this state.
  if (onlyPoint->getWasHit())
    {
      session->getParamNew()->setInt("New State", STATE_ATTACK_DRAWING);
      session->getParamOld()->getInt("Segment Part to Draw", segmentPartToDraw);
      session->getParamNew()->setInt("Segment Part to Draw", segmentPartToDraw);
      return;
    }
}

void StateHandler::stateEndAttackWaitForUser ()
{
}


//Defend Clicking: Paths are drawn, user clicks on them to halt them.
void StateHandler::stateDebugDefendClicking ()
{
}

void StateHandler::stateStartDefendClicking ()
{
  session->setInt("Defense Drawing Start Time", SDL_GetTicks());
  session->getRules()->addDefenseArray("TestDefensePattern");
  session->getRenderer()->stateStartDefendClicking();
}

void StateHandler::stateBeforeDrawDefendClicking ()
{
}

void StateHandler::stateApplyInputDefendClicking ()
{
  /*
Get all DefensePoint locations.
Check to see how many points escaped.
 For each point, see if their x coordinate exceeded windowWidth.
  If so, remove the point and -1 armor from player.
   If player has negative armor, state over
If there is a click,
 edit point locations to represent their onscreen locations
 measure mouse location against it.
  If it's in range, tell DefenseArray to -1 hp from that point and reverse for 1 second.
   If DefensePoint has 0 hp, delete it
If there are NO DefensePoints in the DefenseArray, state over
*/
  vector <int> xLoc, yLoc, rads, indx;
  int defenseTime;
  session->getInt("Defense Drawing Start Time", defenseTime);
  //Get all DefensePoint locations.
  session->getRules()->getDefenseArray().getDefensePointLocations(xLoc, yLoc, rads, indx);
  int battleClickZoneX=0, battleClickZoneY=0;
  int battleClickZoneWidth=0, battleClickZoneHeight=0;
  int battleClickZoneParryWidth=0, battleClickZoneParryHeight=0;

  session->getInt("Battle Clickzone X", battleClickZoneX);
  session->getInt("Battle Clickzone Y", battleClickZoneY);
  battleClickZoneWidth=session->getRules()->getDefenseArray().getWindowWidth();
  battleClickZoneHeight=session->getRules()->getDefenseArray().getWindowHeight();
  battleClickZoneParryWidth=session->getRules()->getDefenseArray().getParryWindowWidth();
  battleClickZoneParryHeight=session->getRules()->getDefenseArray().getParryWindowHeight();

  //get the sides
  int leftSide=battleClickZoneX-(battleClickZoneWidth/2);
  int rightSide=battleClickZoneX+(battleClickZoneWidth/2);
  int topSide=battleClickZoneY-(battleClickZoneHeight/2);
  int bottomSide=battleClickZoneY+(battleClickZoneHeight/2);
  int parryLeft, parryRight;

  if (session->getRules()->getDefenseArray().getMovingLeft())
    {
      parryLeft=leftSide;
      parryRight=rightSide+battleClickZoneParryWidth;
    }
  else
    {
      parryRight=rightSide;
      parryLeft=rightSide-battleClickZoneParryWidth;
    }

  //For each point, see if their x coordinate exceeded windowWidth.
  int index=0;
  for (index=0; index < int(xLoc.size()); index++)
    {
      if (xLoc[index]>=battleClickZoneWidth)
        {
          //If so, remove the point and -1 armor from player.
          session->getRules()->defensePointEscaped(1);
          session->getRules()->getDefenseArray().removeDefensePoint(indx[index]);
          //   If player has negative armor, state over
          if (session->getRules()->playerFailedDefense())
            session->getParamNew()->setInt("New State", STATE_BATTLE_SWITCH_ROUND);
        }
    }

  vector<Input>::iterator inputIter;
  vector<Input>::iterator inputEnd=session->getPlayerInput().getInputs().end();
  inputIter=session->getPlayerInput().getInputs().begin();

  //If there is a click
  if (inputIter!=inputEnd)
    {
      //edit point locations to represent their onscreen locations
      for (index=0; index<int(xLoc.size()) && index<int(yLoc.size()) && index<int(rads.size()) && index<int(indx.size()); index++)
        {
          if(session->getRules()->getDefenseArray().getMovingLeft())
            xLoc[index]=rightSide-xLoc[index];
          else
            xLoc[index]=leftSide+xLoc[index];
          yLoc[index]+=topSide;
        }
    }
  //measure mouse location against it.
  while (inputIter!=inputEnd)
    {
      if (inputIter->getInput()==INPUT_MOUSEDOWN &&
          pointRectangleCollision(inputIter->getData()[0], inputIter->getData()[1],
                                  parryLeft, parryRight, topSide, bottomSide))
        {
          for (index=0; index<int(xLoc.size()) && index<int(yLoc.size()) && index<int(rads.size()) && index<int(indx.size()); index++)
            {
              if(pointCircleCollision(inputIter->getData()[0], inputIter->getData()[1],
                                      xLoc[index], yLoc[index], rads[index]))
                {
                  //If it's in range, tell DefenseArray to -1 hp from that point and reverse for 1 second.
                  //   If DefensePoint has 0 hp, delete it
                  session->getRules()->getDefenseArray().removeHPFromDefensePoint(indx[index], 1);
                  //check for a crititcal defense.
                  session->getRules()->checkForCriticalDefense(indx);
                  //reverse the direction temporarily
                  session->getRules()->getDefenseArray().startReversingDefensePoint(indx[index], DEFENSE_POINT_REVERSE);
                }
            }
        }
      inputIter++;
    }

  //If there are NO DefensePoints in the DefenseArray, state over
  if (session->getRules()->getNumberOfDefensePoints()<=0)
    session->getParamNew()->setInt("New State", STATE_BATTLE_SWITCH_ROUND);
}

void StateHandler::stateEndDefendClicking ()
{
}
