#include "DebugObject.h"
#include "Hero.h"
#include "SpikeBall.h"
#include "Brick.h"
#include "Coin.h"
#include "Spring.h"
#include "MovingPlatform.h"
#include "HUD.h"
#include "ExitBlocker.h"
#include "Checkpoint.h"
#include "Exit.h"
#include <curses.h>
#include "LevelLoader.h"
#include "Position.h"
#include "Box.h"
#include "Clock.h"
#include "GameObject.h"
#include "GameObjectList.h"
#include "GameObjectListIterator.h"
#include "Manager.h"
#include "Event.h"
#include "LogManager.h"
#include "WorldManager.h"
#include "GameManager.h"
#include "ResourceManager.h"
#include <Windows.h>
#include <direct.h> // for getcwd
#include <stdlib.h>// for MAX_PATH

Hero::Hero(){
	//this->setSprite(new Sprite(1));
	WorldManager::getInstance().registerInterest(this,"keyboard");
	this->upDis=0;
	this->state=0;
	this->canJump=false;
	this->colorbg=11;
	this->colorfg=0;
	this->startPos=Position(0,0);
	dir=0;
	numCoins=0;


}
Hero::~Hero(){}
void Hero::move(int dx,int dy){
	GameObject* col=WorldManager::getInstance().isCollision(this,Position(this->getPos().getX()+dx,this->getPos().getY()+dy));
	if(dy<0&&col!=NULL){
		if(col->getType()!="coin"){
			this->upDis=0;
		}
	}

	if(dy>0){
		if(col!=NULL){
			if(col->getType()!="coin"){
				this->canJump=true;
				if(col->getType()=="plat"){
					//static type casting is bad but it works here
					MovingPlatform* mPlat=static_cast <MovingPlatform *>(col);
					if(mPlat->moveDelay==1){
						this->move(mPlat->xs,min(mPlat->ys,0));
					}
				}
			}
		}
		else{
			this->canJump=false;
		}
	}
	if(col==NULL){
		this->setPos(Position(this->getPos().getX()+dx,this->getPos().getY()+dy));
	}
	else{
		if(col->getType()=="check"){
			this->startPos=this->getPos();
		}
		if(col->getType()=="spike"){
			this->setPos(this->startPos);
		}
		if(col->getType()=="coin"){
			//get coin
			this->setPos(Position(this->getPos().getX()+dx,this->getPos().getY()+dy));
			WorldManager::getInstance().markForDelete(col);
			col->setSolid(false);
			Event* e=&Event();
			e->setType("coin");
			WorldManager::getInstance().onEvent(e);
		}
		if(dy>0&&col->getType()=="spring"){
			col->setSprite(ResourceManager::getInstance().getSprite("spring_anim"),true);
			this->canJump=false;
			this->upDis=22;
		}
		if(col->getType()=="exit"){
			//load next level
			//this is very hacky and bad. dont do it. ever.
			//launch game.exe with commandline for next level and then exit
			//parent has a kid and then kills itself orphaning the child. 
			SHELLEXECUTEINFO shExecInfo;
			shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
			shExecInfo.fMask = NULL;
			shExecInfo.hwnd = NULL;
			shExecInfo.lpVerb = NULL;
			shExecInfo.lpFile = L"dragonfly_alpha.exe";
			wstring temp;
			temp.assign(nextLevelName.begin(), nextLevelName.end());
			shExecInfo.lpParameters = temp.c_str();
			shExecInfo.lpDirectory = NULL;
			shExecInfo.nShow = SW_NORMAL;
			shExecInfo.hInstApp = NULL;
			ShellExecuteEx(&shExecInfo);
			exit(1);
		}
	}
}
void Hero::step(){}
int Hero::eventHandler(Event *e){
	if (e->getType() == "step") {
		if(this->upDis>0){
			move(0,-1);
			this->upDis--;
		}
		else{
			move(0,1);
		}
		//if you leave the playfield, move somewhere inside it
		if(!WorldManager::getInstance().boxesIntersect(this->box,WorldManager::getInstance().getBoundary())){
			this->setPos(this->startPos);
		}
		//step();
		int tempx=this->getPos().getX();
		int tempy=this->getPos().getY();
		WorldManager::getInstance().setView(Box(Position(tempx-32,tempy-24),64,48));
		draw();
		return 1;
	}
	if(e->getType()=="keyboard"){
		EventKeyboard *kbdevent = static_cast <EventKeyboard *> (e);
		kbd(kbdevent);
	}
	return 0;
}

void Hero::kbd(EventKeyboard *kbdevent){
	int* keys=kbdevent->getKey();
	if(keys['D']!=0){
		this->move(1,0);
		this->dir=0;
	}
	if(keys['A']!=0){
		this->move(-1,0);
		this->dir=1;
	}
	if(keys['W']!=0&&this->canJump){
		//this->move(0,-1);
		this->canJump=false;
		this->upDis=13;
	}
	if(keys['S']!=0){
		this->move(0,3);
	}

	//animations of the hero
	if(keys['A']==0&&keys['D']==0&&canJump){
		this->sprite_index=0;
		this->setSprite(ResourceManager::getInstance().getSprite("hero_stand"),true);
	}
	if((keys['A']!=0||keys['D']!=0)&&canJump){
		//this->sprite_index=0;
		this->setSprite(ResourceManager::getInstance().getSprite("hero_walk"),true);
	}
	if(!canJump){
		this->sprite_index=0;
		if(dir==0){
			this->setSprite(ResourceManager::getInstance().getSprite("hero_jump_right"),true);
		}
		if(dir==1){
			this->setSprite(ResourceManager::getInstance().getSprite("hero_jump_left"),true);
		}
	}
}