#include "StdInc.h"
#include "CMovementAnimation.h"

#include "CBattleInterface.h"
#include "CCreatureAnimation.h"
#include "../../lib/BattleState.h"
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
#include "CReverseAnimation.h"
#include "CMovementEndAnimation.h"
#include "CClickableHex.h"

bool CMovementAnimation::init()
{
	if( !isEarliest(false) )
		return false;

	//a few useful variables
	steps = static_cast<int>(myAnim()->framesInGroup(CCreatureAnim::MOVING) * owner->getAnimSpeedMultiplier() - 1);
	if(steps == 0) //this creature seems to have no move animation so we can end it immediately
	{
		endAnim();
		return false;
	}
	whichStep = 0;
	int hexWbase = 44, hexHbase = 42;
	const CStack * movedStack = stack;
	if(!movedStack || myAnim()->getType() == 5)
	{
		endAnim();
		return false;
	}
	//bool twoTiles = movedStack->doubleWide();

	SPoint begPosition = CClickableHex::getXYUnitAnim(curStackPos, movedStack->attackerOwned, movedStack, owner);
	SPoint endPosition = CClickableHex::getXYUnitAnim(nextHex, movedStack->attackerOwned, movedStack, owner);

	int mutPos = SBattleHex::mutualPosition(curStackPos, nextHex);

	//reverse unit if necessary
	if((begPosition.x > endPosition.x) && owner->creDir[stack->ID] == true)
	{
		owner->addNewAnim(new CReverseAnimation(owner, stack, curStackPos, true));
		return false;
	}
	else if ((begPosition.x < endPosition.x) && owner->creDir[stack->ID] == false)
	{
		owner->addNewAnim(new CReverseAnimation(owner, stack, curStackPos, true));
		return false;
	}

	if(myAnim()->getType() != CCreatureAnim::MOVING)
	{
		myAnim()->setType(CCreatureAnim::MOVING);
	}
	//unit reversed

	//	if(owner->moveSh <= 0)
	//		owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);

	//step shift calculation
	posX = myAnim()->pos.x, posY = myAnim()->pos.y; // for precise calculations ;]
	if(mutPos == -1 && movedStack->hasBonusOfType(Bonus::FLYING)) 
	{
		steps *= distance;
		steps /= 2; //to make animation faster

		stepX = (endPosition.x - begPosition.x) / static_cast<double>(steps);
		stepY = (endPosition.y - begPosition.y) / static_cast<double>(steps);
	}
	else
	{
		switch(mutPos)
		{
		case 0:
			stepX = -1.0 * (hexWbase / (2.0 * steps));
			stepY = -1.0 * (hexHbase / (static_cast<double>(steps)));
			break;
		case 1:
			stepX = hexWbase / (2.0 * steps);
			stepY = -1.0 * hexHbase / (static_cast<double>(steps));
			break;
		case 2:
			stepX = hexWbase / static_cast<double>(steps);
			stepY = 0.0;
			break;
		case 3:
			stepX = hexWbase / (2.0 * steps);
			stepY = hexHbase / static_cast<double>(steps);
			break;
		case 4:
			stepX = -1.0 * hexWbase / (2.0 * steps);
			stepY = hexHbase / static_cast<double>(steps);
			break;
		case 5:
			stepX = -1.0 * hexWbase / static_cast<double>(steps);
			stepY = 0.0;
			break;
		}
	}
	//step shifts calculated

	return true;
}

void CMovementAnimation::nextFrame()
{
	//moving instructions
	posX += stepX;
	myAnim()->pos.x = static_cast<Sint16>(posX);
	posY += stepY;
	myAnim()->pos.y = static_cast<Sint16>(posY);

	// Increments step count and check if we are finished with current animation
	++whichStep;
	if(whichStep == steps)
	{
		// Sets the position of the creature animation sprites
		SPoint coords = CClickableHex::getXYUnitAnim(nextHex, owner->creDir[stack->ID], stack, owner);
		myAnim()->pos = coords;

		// true if creature haven't reached the final destination hex
		if ((nextPos + 1) < destTiles.size())
		{
			// update the next hex field which has to be reached by the stack
			nextPos++;
			curStackPos = nextHex;
			nextHex = destTiles[nextPos];

			// update position of double wide creatures
			bool twoTiles = stack->doubleWide();
			if(twoTiles && bool(stack->attackerOwned) && (owner->creDir[stack->ID] != bool(stack->attackerOwned) )) //big attacker creature is reversed
				myAnim()->pos.x -= 44;
			else if(twoTiles && (! bool(stack->attackerOwned) ) && (owner->creDir[stack->ID] != bool(stack->attackerOwned) )) //big defender creature is reversed
				myAnim()->pos.x += 44;

			// re-init animation
			for(std::list<std::pair<CBattleAnimation *, bool> >::iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
			{
				if (it->first == this)
				{
					it->second = false;
					break;
				}
			}
		}
		else
			endAnim();
	}
}

void CMovementAnimation::endAnim()
{
	const CStack * movedStack = stack;

	CBattleAnimation::endAnim();

	if(movedStack)
		owner->addNewAnim(new CMovementEndAnimation(owner, stack, nextHex));


	if(owner->moveSh >= 0)
	{
		CCS->soundh->stopSound(owner->moveSh);
		owner->moveSh = -1;
	}

	delete this;
}

CMovementAnimation::CMovementAnimation(CBattleInterface *_owner, const CStack *_stack, std::vector<SBattleHex> _destTiles, int _distance)
: CBattleStackAnimation(_owner, _stack), destTiles(_destTiles), nextPos(0), distance(_distance), stepX(0.0), stepY(0.0)
{
	curStackPos = stack->position;
	nextHex = destTiles.front();
}