#include "Player.hpp"
#include "Echo.hpp"
#include "Animation.hpp"
#include "Shared.hpp"

Player::Player(Shared* context)
{
	armored = true;
	_context = context;
	dead = false;
	iframed = false;
}

Player::~Player()
{

}

void Player::move(float x, float y)
{
	setPosition(getPosition().x + x, getPosition().y + y);

	if(dead) return;
	// if(getPosition().x < getOrigin().x) {
		// setPosition(getOrigin().x, getPosition()_settings.cb.emplace_back(53 * 16, 13 * 16, 16, 16);.y);
	// }
	if(getPosition().x < 128.f) {
		x = 0.f;
	}
	if(getPosition().y > 0.f) {
		y = 0.f;
	}
	_context->view->move(x, y);
	_context->evm->move(x * 0.95f, y * 0.95f);
	_context->bg->move(x, y);
	_context->fog->move(x, y);
}

void Player::move(float x)
{
	Player::move(x, 0.f);
}

void Player::loop(float delta)
{
	bool right = (Keyboard::isKeyPressed(Keyboard::D) || Keyboard::isKeyPressed(Keyboard::Right)) && !dead;
	bool left = (Keyboard::isKeyPressed(Keyboard::A) || Keyboard::isKeyPressed(Keyboard::Left)) && !dead;
	bool jump =_context->jump;
	static Clock jumpClock;

	if(getPosition().y > 224.f + 32.f) {
		dead = true;
	}

	if(armored) {
		setOrigin(16.f, 29.f);
	}
	else {
		setOrigin(16.f, 25.f);
	}

	bool bottomCol = false;
	for(unsigned i = 0; i < _context->cp.size() && !bottomCol; ++i) {
		if(((getPosition().x >= _context->cp[i].left && getPosition().x <= _context->cp[i].left + _context->cp[i].width) ||
		   (getPosition().x - 8.f * getScale().x >= _context->cp[i].left && getPosition().x - 8.f * getScale().x <= _context->cp[i].left + _context->cp[i].width)) &&
		   getPosition().y >= _context->cp[i].top && getPosition().y <= _context->cp[i].top + _context->cp[i].height) {
			if(_velocity > 0.f && !dead) {
				move(0, -getPosition().y + _context->cp[i].top);
			}
			bottomCol = true;
		}
	}
	for(unsigned i = 0; i < _context->cb.size() && !bottomCol; ++i) {
		//if(getPosition().x >= _context->cb[i].left + 4.f && getPosition().x <= _context->cb[i].left - 4.f + _context->cb[i].width &&
		//   getPosition().y >= _context->cb[i].top && getPosition().y <= _context->cb[i].top + _context->cb[i].height) {
		if(((getPosition().x >= _context->cb[i].left && getPosition().x <= _context->cb[i].left + _context->cb[i].width) ||
		   (getPosition().x - 8.f * getScale().x >= _context->cb[i].left && getPosition().x - 8.f * getScale().x <= _context->cb[i].left + _context->cb[i].width)) &&
		   getPosition().y >= _context->cb[i].top && getPosition().y <= _context->cb[i].top + _context->cb[i].height) {
			if(_velocity > 0.f && !dead) {
				move(0, -getPosition().y + _context->cb[i].top);
			}
			bottomCol = true;
		}
	}
	if(dead) {
		bottomCol = false;
	}
	if(iframeclock.getElapsedTime().asSeconds() > 4.f) {
		setColor(Color::White);
		iframed = false;
	}
	else {
		setColor(Color(255, 255, 255, rand() % 155 + 100));
	}
	for(unsigned i = 0; i < _context->hz.size(); ++i) {
		if(iframed) {
			break;
		}
		if(getPosition().x >= _context->hz[i].left && getPosition().x <= _context->hz[i].left + _context->hz[i].width &&
		   getPosition().y >= _context->hz[i].top && getPosition().y <= _context->hz[i].top + _context->hz[i].height) {
			   ///front!
			   if(armored) {
				   _jumping = true;
				   _velocity = -192.f;
				   _jumpDirection = getScale().x * -1.f;
				   armored = false;
				   setAnimation("jump", armored);
				   iframeclock.restart();
				   iframed = true;
		   	   }
			   else {
				   dead = true;
				   _velocity = 192.f;
			   }
			   break;
		}
		if(getPosition().x - 8.f * getScale().x >= _context->hz[i].left && getPosition().x - 8.f * getScale().x <= _context->hz[i].left + _context->hz[i].width &&
		   getPosition().y >= _context->hz[i].top && getPosition().y <= _context->hz[i].top + _context->hz[i].height) {
			   ///back!
			   if(armored) {
				   armored = false;
				   _jumping = true;
				  _velocity = -192.f;
				  _jumpDirection = getScale().x;
				  setScale(getScale().x * -1.f, 1.f);
				   setAnimation("jump", armored);
				   iframeclock.restart();
				   iframed = true;
		   	   }
			   else {
				   dead = true;
				   _velocity = 192.f;
			   }
		}
	}

	if(_jumping) {
		if(jumpClock.getElapsedTime().asSeconds() > 0.1f) {
			move(delta * 85.f * _jumpDirection, delta * _velocity);
			if(_velocity < 0.f) {
				_velocity -= delta * (_velocity - 900.f);
			}
			else {
				_velocity += delta * (_velocity + 450.f);
			}
			if(_velocity > 0.f && bottomCol) {
				_jumping = false;
				setAnimation("idle", armored);
			}
		}
		if(left && !right) {
			setScale(-1.f, 1.f);
		}
		else if(!left && right) {
			setScale(1.f, 1.f);
		}
	}
	else {
		if(left && !right) {
			float speed = -85.f;
			for(unsigned i = 0; i < _context->cb.size(); ++i) {
				if(getPosition().x - getOrigin().x + 12.f > _context->cb[i].left && getPosition().x - getOrigin().x + 12.f < _context->cb[i].left + _context->cb[i].width &&
				   getPosition().y - 8.f > _context->cb[i].top && getPosition().y - 8.f < _context->cb[i].top + _context->cb[i].height) {
					move(-getPosition().x + _context->cb[i].left + _context->cb[i].width + getOrigin().x - 12.f, 0);
					speed = 0.f;
					break;
				}
			}
			move(delta * speed, 0.f);
			setScale(-1.f, 1.f);
			setAnimation("walk", armored);
		}
		else if(right && !left) {
			float speed = 85.f;
			for(unsigned i = 0; i < _context->cb.size(); ++i) {
				if(getPosition().x + getOrigin().x - 12.f > _context->cb[i].left && getPosition().x + getOrigin().x - 12.f < _context->cb[i].left + _context->cb[i].width &&
				   getPosition().y - 8.f > _context->cb[i].top && getPosition().y - 8.f < _context->cb[i].top + _context->cb[i].height) {
					move(-getPosition().x + _context->cb[i].left - getOrigin().x + 12.f, 0);
					speed = 0.f;
					break;
				}
			}
			move(delta * speed, 0.f);
			setScale(1.f, 1.f);
			setAnimation("walk", armored);
		}
		else if(_current->name == "walk") {
			setAnimation("idle", armored);
		}
		if(jump && bottomCol) {
			bool rekt = false;
			for(unsigned i = 0; i < _context->tpa.size(); ++i) {
				if(_context->tpa[i].x * 16.f + 16.f >= getPosition().x && _context->tpa[i].x * 16.f <= getPosition().x
			     && _context->tpa[i].y * 16.f + 16.f >= getPosition().y && _context->tpa[i].y * 16.f <= getPosition().y) {
					rekt = true;
					setAnimation("forward", armored);
					move(16.f * (_context->tpb[i].x - _context->tpa[i].x), 16.f * (_context->tpb[i].y - _context->tpa[i].y));
					break;
				}
			}
			if(!rekt) {
				_jumping = true;
				_velocity = -256.f;
				_jumpDirection = right - left;
				jumpClock.restart();
				setAnimation("jump", armored);
			}
		}
		if(!bottomCol) {
			_jumping = true;
			_velocity = 384.f;
			_jumpDirection = 0;
			setAnimation("longidle", armored);
		}
	}

	animate();
}

void Player::animate()
{
	if(_current == nullptr) {
		return;
	}
	const unsigned duration = _current->duration;
 	unsigned elapsed = _anclock.getElapsedTime().asMilliseconds() % duration;
	unsigned frame = (elapsed * _current->count) / duration;
	setTextureRect(IntRect(_current->tex.getSize().x * frame / _current->count, 0,
						_current->tex.getSize().x / _current->count, _current->tex.getSize().y));

	if(!_current->loop) {
		if(elapsed + _current->duration <= _anclock.getElapsedTime().asMilliseconds()) {
			if(!_jumping) {
				setAnimation("idle", armored);
			}
			else {
				//setAnimation("jump");
				setTextureRect(IntRect(_current->tex.getSize().x - _current->tex.getSize().x / _current->count, 0,
									_current->tex.getSize().x / _current->count, _current->tex.getSize().y));
			}
		}
	}
}
