
#include <sstream>

#include "cacher.h"
#include "material.h"
#include "block.h"
#include "tweak/tweak.h"

namespace block {


Cacher::Cacher() {
}

bool Cacher::should_draw(C3f p,int side,int level) {
		//if (p.x<=0) return false;
		//if (p.x>=1) return false;
		if (p.y<=0&&side==1) return false;
		if (p.y>=1&&side==1) return false;
		//if (p.z<=0) return false;
		//if (p.z>=1) return false;


	std::ostringstream sstr;
	sstr << p << "- " << side << "-" << level;

	std::map<std::string,unsigned char>::iterator it;
	it=corners.find(sstr.str());
	if (it==corners.end()) {
		std::cout << "inv " << std::endl;
		return true;
	}
	if ((*it).second==1){
		stat_drawn++;
		return true;
	} else {
		stat++;
		return false;
	}
	
}

bool Cacher::count_corner(C3f p,int side,int level) {
	std::ostringstream sstr;
	sstr << p << "- " << side << "-" << level;

	std::map<std::string,unsigned char>::iterator it;
	it=corners.find(sstr.str());
	if (it==corners.end()) {
		corners.insert(corners.end(),std::make_pair(sstr.str(),1));
	
		return false;
	}
	(*it).second++;
	return true;
}

void Cacher::cache(Block *b,unsigned int l) {
	level=l;
	
	stat=0;
	stat_drawn=0;

	Blockinfo3 bi;
	bi.block_=b;
	count(bi);

	bi=Blockinfo3();
	bi.block_=b;
	paint(bi,false);

	//std::cout << "stat: " << stat << " /  " << stat_drawn << "  .... " << corners.size() << std::endl;
}

void Cacher::count(Blockinfo3 bi) {
	if (bi.block_->is_splitted()) {
		for (unsigned int i=0;i<8;i++) {
			count(bi.get_descend(i));
		}
		return;
	}
	E_Material mat;
	mat=bi.block_->get_material();
	if (mat==M_NONE) { return; }
	count_corner(bi.pos_,0,bi.level_);
	count_corner(bi.pos_+C3f(bi.scale_,0,0),0,bi.level_);
	count_corner(bi.pos_,1,bi.level_);
	count_corner(bi.pos_+C3f(0,bi.scale_,0),1,bi.level_);
	count_corner(bi.pos_,2,bi.level_);
	count_corner(bi.pos_+C3f(0,0,bi.scale_),2,bi.level_);

}

void Cacher::paint(Blockinfo3 bi,bool draw) {
	if (bi.block_->is_splitted()) {

		if (bi.level_==level) {
			GLuint dl;

			dl=glGenLists(1);
			glNewList(dl,GL_COMPILE);
			for (unsigned int i=0;i<8;i++) {
				paint(bi.get_descend(i),true);
			}
			glEndList();
			bi.block_->displaylist=dl;
		} else {
			for (unsigned int i=0;i<8;i++) {
				paint(bi.get_descend(i),draw);
			}
		}
		return;
	}
	E_Material mat;
	mat=bi.block_->get_material();
	if (mat==M_NONE) { return; }

	if (!draw) return;

	bool dodraw[6];

	dodraw[0]=false;
	if (should_draw(bi.pos_,0,bi.level_)) { dodraw[0]=true; }
	dodraw[1]=false;
	if (should_draw(bi.pos_+C3f(bi.scale_,0,0),0,bi.level_)) { dodraw[1]=true; }
	dodraw[2]=false;
	if (should_draw(bi.pos_,1,bi.level_)) { dodraw[2]=true; }
	dodraw[3]=false;
	if (should_draw(bi.pos_+C3f(0,bi.scale_,0),1,bi.level_)) { dodraw[3]=true; }
	dodraw[4]=false;
	if (should_draw(bi.pos_,2,bi.level_)) { dodraw[4]=true; }
	dodraw[5]=false;
	if (should_draw(bi.pos_+C3f(0,0,bi.scale_),2,bi.level_)) { dodraw[5]=true; }

	bool pushed=false;
	for (unsigned int i=0;i<6;i++) {
		if (!dodraw[i]) continue;
		if (!pushed) {
			glPushMatrix();
			glTranslatef(bi.pos_.x,bi.pos_.y,bi.pos_.z);	
			glScalef(bi.scale_,bi.scale_,bi.scale_);
			pushed=true;
		}
		draw_material(mat,i);
	}
	if (pushed) {
		glPopMatrix();
	}
}


} //namespace
