#include "GameObject.h"
#include "Event.h"
#include "Sprite.h"
#include "LogManager.h"
#include "WorldManager.h"
#include <curses.h>
#include <Windows.h>

GameObject::GameObject(){
	WorldManager::getInstance().registerInterest(this,"step");
	this->setSpriteSlowdownCount(0);
}
GameObject::~GameObject(){}
void GameObject::setId(int new_id){
	this->id=new_id;
}
int GameObject::getId(){
	return this->id;
}
void GameObject::setType(string new_type){
	this->type=new_type;
}
string GameObject::getType(){
	return this->type;
}
void GameObject::setSolid(bool solid){
	this->is_solid=solid;
}
bool GameObject::isSolid(){
	return this->is_solid;
}
void GameObject::setPos(Position new_pos){
	this->pos=new_pos;
}
Position GameObject::getPos(){
	return this->pos;
}
void GameObject::setBox(Box new_box){
	this->box=new_box;
}
Box GameObject::getBox(){
	return this->box;
}
void GameObject::setAltitude(int new_altitude){
	this->altitude=new_altitude;
}
int GameObject::getAltitude(){
	return this->altitude;
}

///// Functions many objects will override.
//TODO
int GameObject::eventHandler(Event *e){
	//LogManager::getInstance().writeLog("Object: ID=%d recieved a step event\n",getId());
	if(e->getType()=="step"){
		//this->box=Box(this->pos,this->p_sprite->getWidth(),this->p_sprite->getHeight());
	}
	return 0;
}
void GameObject::draw(){
	//this->box=Box(this->pos,this->p_sprite->getWidth(),this->p_sprite->getHeight());
	this->box.setCorner(this->pos);
	this->box.setHorizontal(this->box.getHorizontal());
	this->box.setVertical(this->box.getVertical());
	//if the object's box intersects the view box, draw it
	Position camOrigin=WorldManager::getInstance().getView().getCorner();
	string str;
	str=this->p_sprite->getFrame(this->getSpriteIndex()).getString();
	//init_pair(this->getId()+1,this->colorfg,this->colorbg);
	attron(COLOR_PAIR(this->colorbg*16+this->colorfg));
	if(WorldManager::getInstance().boxesIntersect(this->getBox(),WorldManager::getInstance().getView())){
		for(int i=0;i<this->getSprite()->getHeight();i++){
			for(int j=0;j<this->getSprite()->getWidth();j++){
				char c=str[j+(this->getSprite()->getWidth()+1)*i];
				if(c!='`'){
					chtype ch=0;
					//ch+=((c << PDC_COLOR_SHIFT) & A_COLOR);
					//ch+=(c|A_COLOR);
					ch=c;
					mvaddch(this->pos.getY()+i-camOrigin.getY(),this->pos.getX()+j-camOrigin.getX(),ch);
					//printf("a");
					//int foo=mvgetch(this->pos.getY()+i-camOrigin.getY(),this->pos.getX()+j-camOrigin.getX());
				}
			}
		}
	}
	attroff(COLOR_PAIR(this->colorbg*16+this->colorfg));
	//do animation things
	if(this->sprite_slowdown!=-1){
		if(this->sprite_slowdown_count==0){
			this->sprite_index=(this->sprite_index+1)%this->p_sprite->getFrameCount();
			this->sprite_slowdown_count=this->sprite_slowdown;
		}
		else{
			this->sprite_slowdown_count--;
		}
	}
	//mvaddstr(0,0,"AAAAAA");
}

/// Set object sprite to new one.
/// If set_box is true, set bounding box to size of sprite (default is true).
void GameObject::setSprite(Sprite *p_new_sprite){
	this->p_sprite=p_new_sprite;
}
void GameObject::setSprite(Sprite *p_new_sprite, bool set_box){
	this->p_sprite=p_new_sprite;
	if(set_box){
		this->box=Box(this->pos,p_new_sprite->getWidth(),p_new_sprite->getHeight());
	}
}
Sprite* GameObject::getSprite(){
	return this->p_sprite;
}

/// Indicates if sprite is centered at object Position (pos).
bool GameObject::isCentered(){
	return this->sprite_center;
}
void GameObject::setCentered(bool centered){
	this->sprite_center=centered;
}

/// The index of current Sprite frame to be displayed.
void GameObject::setSpriteIndex(int new_sprite_index){
	this->sprite_index=new_sprite_index;
}
int GameObject::getSpriteIndex(){
	return this->sprite_index;
}

/// Slows down sprite animations (in multiples of WorldManager frame time).
void GameObject::setSpriteSlowdown(int new_sprite_slowdown){
	this->sprite_slowdown=new_sprite_slowdown;
}
int GameObject::getSpriteSlowdown(){
	return this->sprite_slowdown;
}
void GameObject::setSpriteSlowdownCount(int new_sprite_slowdown_count){
	this->sprite_slowdown_count=new_sprite_slowdown_count;
}
int GameObject::getSpriteSlowdownCount(){
	return this->sprite_slowdown_count;
}

void GameObject::logDebugInfo(){
	LogManager::getInstance().writeLog("Information for object %d:\n",getId());
	LogManager::getInstance().writeLog("Object is located at: %d, %d\n",getPos().getX(),getPos().getY());
	LogManager::getInstance().writeLog("Object type is: %s\n",getType().c_str());
	LogManager::getInstance().writeLog("----------------\n");
}

void GameObject::setColor(int bg, int fg){
	this->colorbg=bg;
	this->colorfg=fg;
}