#include "actions.h"
#include "printer.h"

/*! \brief Move position according to direction command */
void move_pos(int *row, int *col, command dir);

/*! \brief Implements the NOCMD action; also serves as default action */
void action_none(Level *level, character *pc);

/*! \brief Implements all the move actions, includes check for occupied space */
void action_move(Level *level, character *pc, command cmd);

/*! \brief Implements the melee attack action */
void action_attack(Level *level, character *pc);

/*! \brief Implements the melee attack action, given the direction of the attack */
void action_attack_direction(Level *level, character *pc, command dir);

void action(Level *level, character *pc, command cmd){
	switch (cmd) {
		case NOCMD:   action_none(level, pc); break;
		case UP:	    /* All move actions implemented by the same function */
		case DOWN:    
		case LEFT:    
		case RIGHT:   
		case UPLEFT:  
		case UPRIGHT: 
		case DWLEFT:  
		case DWRIGHT: action_move(level, pc, cmd); break;
		case PICK:    /*! \todo PICK not yet implemented */
		case DROP:    /*! \todo DROP not yet implemented */ action_none(level, pc); break;
		case ATTACK:  action_attack(level, pc); break;
		case FIRE:    /*! \todo FIRE not yet implemented */
		case CAST:    /*! \todo CAST not yet implemented */
		case EAT:     /*! \todo EAT not yet implemented */
		case READ:    /*! \todo READ not yet implemented */
		case USE:     /*! \todo USE not yet implemented */
		case SAVE:    /*! \todo SAVE not yet implemented */
		case REST:    /*! \todo REST not yet implemented */
		case QUIVER:  /*! \todo QUIVER not yet implemented */
		case WIELD:   /*! \todo WIELD not yet implemented */
		default : action_none(level, pc);
	}
}

void action_none(Level *level, character *pc){
	/* empty on purpose */
}

void action_move(Level *level, character *pc, command cmd){
	int row=pc->row;
	int col=pc->col;
	occupation state;
	move_pos(&row,&col,cmd);
	state = can_move_to(level, row, col);
	switch (state) {
		case BUSY: print_msg("Cannot move there..."); break;
		case FREE: pc->row=row; pc->col=col; break;
		case ATCK: action_attack_direction(level, pc, cmd); break;
	}
}

/*! \brief Critical hit rule: if roll >= 16, add more damage */
int critical_damage(int roll){
	switch (roll) {
		case 20 : return 4;
		case 19 : return 3;
		case 18 : return 2;
		case 17 : return 1;
		case 16 : return 1;
		default : return 0;
	}
}

void action_attack_direction(Level *level, character *pc, command dir){
	monster *enemy=NULL;
	int roll=0;
	int erow=pc->row;
	int ecol=pc->col;
	int bonus=character_melee_attack_bonus(pc);
	move_pos(&erow,&ecol,dir);
	enemy=find_monster_at(level, erow, ecol);
	roll=d20();
	if (roll+bonus >= enemy->species->speed) {
		int dmg = character_melee_damage_bonus(pc) + 1 + critical_damage(roll); /*! \todo Only unarmed damage is supported right now */
		enemy->hits-=dmg;
		if (enemy->hits<=0) {
			print_msg("%s hit for %d damage and killed", enemy->species->name, dmg);
			/*! \todo Drop treasure from dead monster */
			/*! \todo Add XP for dead monster */
			remove_monster_from_level(level, enemy);
		} else
			print_msg("%s hit for %d damage", enemy->species->name, dmg);
	} else {
		print_msg("You missed!");
	}
}

void move_pos(int *row, int *col, command dir){
	switch (dir) {
		case UP:	    *row-=1; break;
		case DOWN:    *row+=1; break;
		case LEFT:    *col-=1; break;
		case RIGHT:   *col+=1; break;
		case UPLEFT:  *row-=1; *col-=1; break;
		case UPRIGHT: *row-=1; *col+=1; break;
		case DWLEFT:  *row+=1; *col-=1; break;
		case DWRIGHT: *row+=1; *col+=1; break;
	}	
}

void action_attack(Level *level, character *pc){
	action_attack_direction(level, pc, get_move_command());
}

