#include "player.h"
#include "console.h"
#include "map.h"
#include "block.h"
#include "wall.h"
#include "main.h"
#include <assert.h>

// colors for each player
int colors[] = {CYAN, BRIGHTBLUE, PURPLE, BROWN};
// movement keys for each player
char keys[][9] = {",.loiujm","xcdewqaz","",""};

player::player(int n) {
  setchar('*');
  setcol(colors[n]);
  resetscore();
  resetbonus();
  live = true;
  player_number = n;
  settype("player");
}
void player::move(char c) {
	for (int i = 0; i < strlen(keys[player_number]); i++)
	{
		if (c == keys[player_number][i])
			return move(i);
	}
}
void player::move(int dir) {
  if (!live) return;
  sprite* s = m->spriteat(x + DIRX[dir], y + DIRY[dir]);
  if (s == NULL) {
	m->setsprite(x, y, NULL);
	int test = setpos(x + DIRX[dir], y + DIRY[dir]);
	if (test == 0) {
		m->setsprite(x, y, this);
		return;
	}
	// i did this whith threads in mind. in the unlikely event something
	// moved into the new x y position between the first test and the
	// setpos, this player dies and is docked points, 1 is a beast of
	// any type, 2 is an egg, 3 is a wall
	switch (test) {
	  case 1:
		incscore(-5);
		live = false;
		return;
		// bigger penalty if you somehow run into a moving egg
	  case 2:
		incscore(-10);
		live = false;
		return;
		// this should never happen.
	  case 3:
		std::cout << "moving walls?" << std::flush;
		return;
	}
	return;
  }
  // now if the spot we were trying to move to does contain a sprite...
  if (s->mytype() == "block") {
	// push the block, or try, anyway.
	int p = ((block *)s)->push(x + DIRX[dir], y + DIRY[dir], dir);
	if (p == -1) return;
	m->setsprite(x, y, NULL);
	setpos(x + DIRX[dir], y + DIRY[dir]);
	m->setsprite(x, y, this);
	// the block push function will return an appropriate score if
	// anything got squished.
	incscore(p);
	return;
  }
  // now, if you just flat out run into something deadly, you lose even
  // more points.
  if (s->mytype() == "beast" || s->mytype() == "baby" ||
	  s->mytype() == "super") {
	incscore(-10);
	m->setsprite(x, y, NULL);
	live = false;
	return;
  }
  if (s->mytype() == "egg") {
	incscore(-20);
	live = false;
	return;
  }
  if (s->mytype() == "wall" && ((wall *)s)->isexplode()) {
	incscore(-20);
	m->setsprite(x, y, NULL);
	live = false;
	return;
  }
  return;
}
int player::setpos(int px, int py) {
  std::string s = "";
  if (m->spriteat(px, py) == NULL) {
	s = "null";
  }
  else s = m->spriteat(px, py)->mytype();
  if (s == "block" || s == "null") {
	x = px; y = py;
	return 0;
  }
  // if for some reason we can't move to the specified coordinates, send
  // back something that tells what was in the way.
  if (s == "beast" || s == "baby" || s == "super") return 1;
  if (s == "egg") return 2;
  if (s == "wall") return 3;
}
void player::incscore(int s) {
  // you don't get points if your dead!
  if (!live) return;
  score += s;
}
void player::incbonus(int b) {
  // likewise with bonuses
  if (!live) return;
  bonusmult += b;
}
void player::resetscore() {
  score = 0;
}
void player::resetbonus() {
  bonusmult = 1;
}
bool player::isalive() {
  return live;
}
void player::setlive(bool dolive) { live = dolive; }
int player::squish(int dir) {
  if (!live) return -1;

  sprite* s = m->spriteat(x + DIRX[dir], y + DIRY[dir]);
  if (s == NULL) return -1;

  if (s->mytype() == "block" || s->mytype() == "wall") {
	  incscore(-10);
	  live = false;
	  return 10;
  }
  return -1;
}

int player::getx() { return x; }
int player::gety() { return y; }

int player::getscore() {return score;}
int player::getbonus() {return bonusmult;}
