#include ".\maincharacter.h"

MainCharacter::MainCharacter( CharacterManager* characterManager, CollisionManager* collisionManager, TextManager* newText, DialogueManager* newDialogue, int tileX, int tileY, int dialogue ) : Character( characterManager, collisionManager, newText, newDialogue, tileX, tileY, dialogue ){
	location = WORLD;

	// Fill in states
	RECT* boundingBox = new RECT(); boundingBox->left  = 18; boundingBox->top    = 51;
	                                boundingBox->right = 34; boundingBox->bottom = 59;
    addSpriteState(0, 0, 6, boundingBox, 50, 68, Character::STATE::WALKING);

    boundingBox = new RECT(); boundingBox->left  = 33; boundingBox->top    = 71;
	                          boundingBox->right = 49; boundingBox->bottom = 79;
    addSpriteState(200, 0, 4, boundingBox, 80, 104, Character::STATE::ATTACK);

    boundingBox = new RECT(); boundingBox->left  = 33; boundingBox->top    = 71;
                              boundingBox->right = 49; boundingBox->bottom = 79;
    addSpriteState(200, 0, 1, boundingBox, 80, 104, Character::STATE::ATTACK_READY);

    boundingBox = new RECT(); boundingBox->left  = 18; boundingBox->top    = 51;
	                          boundingBox->right = 34; boundingBox->bottom = 59;
    addSpriteState(0, 408, 4, boundingBox, 50, 68, Character::STATE::IDLE);

    boundingBox = new RECT(); boundingBox->left  = 18; boundingBox->top    = 51;
	                          boundingBox->right = 34; boundingBox->bottom = 59;
    addSpriteState(0, 680, 2, boundingBox, 50, 68, Character::STATE::CASTING);



    pushState(Character::STATE::CREATION);
    setSpriteState( stateStack.top() );
    pushOrPop = false;

	setHeadTextureId( 69 );
	setClip( GameCore::DIRECTION::DOWN );
	setTextureId( 5, tileX, tileY, 1024, 1024, currentSpriteState->boundingBox );

    HP_MAX = 300;
	HP = 300;
    MP = 200;
	MP_MAX = 200;
    strength = 7;

	setPosition( tileX, tileY, currentSpriteState->boundingBox );
	
	characterSprite->setModulationColor( D3DCOLOR_RGBA( 255, 255, 255, 255 ) );
}

MainCharacter::~MainCharacter(void){
}

void MainCharacter::collide( Character* moveChar ) {
    GameCore::DIRECTION move;
	if( moveChar->getType() == Character::ENEMY ) {
        if(moveChar->getFacing() == GameCore::DIRECTION::DOWN){
            move = GameCore::DIRECTION::UP;
        } else if(moveChar->getFacing() == GameCore::DIRECTION::UP){
            move = GameCore::DIRECTION::DOWN;
        } else if(moveChar->getFacing() == GameCore::DIRECTION::RIGHT){
            move = GameCore::DIRECTION::RIGHT;
        } else if(moveChar->getFacing() == GameCore::DIRECTION::LEFT){
            move = GameCore::DIRECTION::LEFT;
        }

        setClip( move );
        attacker = moveChar;
        if(stateStack.top() != Character::STATE::ATTACKED){
            pushState(Character::STATE::ATTACKED);
        }

//        characterManager->moveCharacter( this, move );
//	    characterManager->moveCharacter( this, move );
//	    characterManager->moveCharacter( this, move );
//	    characterManager->moveCharacter( this, move );
    }
}

Character::TYPE MainCharacter::getType() {
	return Character::TYPE::MAIN;
}

void MainCharacter::setSpriteState( Character::STATE aState ) {
    switch(aState){
        case Character::STATE::ATTACK:
            currentSpriteState = getSpriteState(Character::STATE::ATTACK);
            break;
        case Character::STATE::ATTACK_READY:
            currentSpriteState = getSpriteState(Character::STATE::ATTACK_READY);
            break;
        case Character::STATE::ATTACKED:
            currentSpriteState = getSpriteState(Character::STATE::WALKING);
            break;
        case Character::STATE::CREATION:
            currentSpriteState = getSpriteState(Character::STATE::WALKING);
            break;
        case Character::STATE::DEAD:
            currentSpriteState = getSpriteState(Character::STATE::WALKING);
            break;
        case Character::STATE::DYING:
            currentSpriteState = getSpriteState(Character::STATE::WALKING);
            break;
        case Character::STATE::IDLE:
            currentSpriteState = getSpriteState(Character::STATE::IDLE);
            break;
        case Character::STATE::WALKING:
            currentSpriteState = getSpriteState(Character::STATE::WALKING);
            break;
        case Character::STATE::MAGIC:
            currentSpriteState = getSpriteState(Character::STATE::WALKING);
            break;
        case Character::STATE::CASTING:
            currentSpriteState = getSpriteState(Character::STATE::CASTING);
            break;
    }
}

void MainCharacter::creation(){
    pushState(Character::STATE::IDLE);
}

void MainCharacter::idle(){
//GameError("idle\n");
	if ( yOffset >= currentSpriteState->numFrames ){
		yOffset = 0;
    }
    animateSprite(Character::SPEED::HUNDREDTH);
}

void MainCharacter::walking(){
//GameError("walking\n");
	if ( yOffset > currentSpriteState->numFrames ){
		yOffset = 0;
    }
    if(isWalking){
        while(movement.size() > 0){
            characterManager->moveCharacter(this, movement.front());
            movement.pop();
        }
        animateSprite(Character::SPEED::FIFTH);
    } else {
        while(movement.size() > 0){
            movement.pop();
        }
        popState();
    }
}

void MainCharacter::dying(){
//GameError("dying\n");
	if( alpha > 0 ) {
		alpha -= 32;
	} else {
        pushState(Character::STATE::DEAD);
	}
	characterSprite->setModulationColor( D3DCOLOR_RGBA( 255, 255, 255, alpha ) );
}

void MainCharacter::attacked(){
//GameError("attacked\n");
    takeDamage();
    GameCore::DIRECTION move;
    if(attackedFrom == GameCore::DIRECTION::DOWN){
        move = GameCore::DIRECTION::UP;
    } else if(attackedFrom == GameCore::DIRECTION::UP){
        move = GameCore::DIRECTION::DOWN;
    } else if(attackedFrom == GameCore::DIRECTION::LEFT){
        move = GameCore::DIRECTION::RIGHT;
    } else if(attackedFrom == GameCore::DIRECTION::RIGHT){
        move = GameCore::DIRECTION::LEFT;
    }
		characterManager->moveCharacter( this, move );
		characterManager->moveCharacter( this, move );
		if( (attackedFrom == GameCore::DOWN) || (attackedFrom == GameCore::UP)){
			characterManager->moveCharacter( this, move );
			characterManager->moveCharacter( this, move );
		} 
	setClip( attackedFrom );
	if( getHP() <= 0 ) {
	    pushState( Character::DEAD );
	}
    else{
        popState();
    }
}

void MainCharacter::attack(){
//GameError("Attack!!\n");
    if ( yOffset == 1 ){
    	characterManager->checkAttack(this);
        characterManager->playSound( 5 );
    }
	if ( yOffset > currentSpriteState->numFrames ){
		popState(); // one for attack
        popState(); // one for attack ready
        isAttacking = false;
        isAttackReady = false;
    } else {
        animateSprite(Character::SPEED::NORMAL);
    }
}

void MainCharacter::attackReady(){
//GameError("attack ready\n");
	if ( yOffset > currentSpriteState->numFrames ){
        isAttacking = true;
    } else {
        animateSprite(Character::SPEED::NORMAL);
    }
}

void MainCharacter::dead(){
//GameError("dead\n");
}

void MainCharacter::magic() {
//GameError("magic");
    
    isCasting = false;
    if( MP > 0 ) {
        pushState(Character::STATE::CASTING);
    } else {
        popState();
    }
}

void MainCharacter::casting() {
//GameError("casting");
    if(!isCasting){
        isCasting = true;
        isDoneCasting = false;

        RECT* box = new RECT;
		box->bottom = getBoundingBox()->bottom + getY();
		box->top = getBoundingBox()->top + getY();
		box->left = getBoundingBox()->left + getX();
		box->right = getBoundingBox()->right + getX();

		int heightDiff = box->bottom - box->top;
		int widthDiff = box->right - box->left;

		int fireX = box->left + (widthDiff/2);
        int fireY = getY() + currentSpriteState->height/2;

		switch( facing ) {
			case GameCore::DIRECTION::RIGHT:
				fireX += (widthDiff/2) + 15;
				fireX += 15;
				break;
			case GameCore::DIRECTION::LEFT:
				fireX -= (widthDiff/2);
				fireX -= 30;
				break;
			case GameCore::DIRECTION::UP:
				fireY -= 25;
				break;
			case GameCore::DIRECTION::DOWN:
				fireY += 35;
				break;
		}
		TILE* tile = getTile();
		Fireball* fire = new Fireball(this, characterManager, collisionManager, textManager, dialogueManager,tile->x,tile->y+2, facing, -1);
		fireX = fireX - fire->getBoundingBox()->left - ((fire->getBoundingBox()->right - fire->getBoundingBox()->left)/2);
		fireY = fireY - fire->getBoundingBox()->top - ((fire->getBoundingBox()->bottom - fire->getBoundingBox()->top)/2);
		
		fire->setX( fireX );
		fire->setY( fireY );
		characterManager->addCharacter(fire);
		MP--;
    } else if(!isDoneCasting){
        animateSprite(Character::SPEED::NORMAL);
    } else if (isDoneCasting){
        isCasting = false;
        popState(); // pop casting
        popState(); // pop magic
    }
}

void MainCharacter::addMovement(GameCore::DIRECTION direction){
    if (movement.size() < 1){
        movement.push(direction);
    } else if ((movement.size() < 2) && (direction != movement.front())){
        movement.push(direction);
    }
}

int MainCharacter::getLevel(){
    return ((experience - (experience % 100))/100);
}

int MainCharacter::expNeededforNextLevel(){
    return (100 - (experience % 100));
}

int MainCharacter::getStrength(){
    return strength + 2 * getLevel();
}
