#include "SDL.h"
#include "SDL_opengl.h"

#include "map2.h"
#include "cube.h"
#include <time.h>

#include "painter3.h"
#include "painter6.h"
#include "debugger.h"
#include "collider.h"
#include "selector2.h"
#include "destructor.h"
#include "merger.h"
#include "cacher.h"
#include "random.h"

#include "tweak/tweak.h"

#include <sstream>
namespace block {


void Map2::init(std::string name) {
	load(name);
}

std::string path="";
void Map2::set_path(std::string s) {
	path=s;
	std::cout << "setpath " << s << "  " << path << std::endl;
}

void Map2::select(unsigned int x,unsigned int y,int button) {
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glPushMatrix();
	float scale=Tweak::blockscale_f();
	glScalef(scale,scale,scale);

	Selector2 selector;
	selector.select(&block,x,y);

	glPopMatrix();

	selected=selector.get_result();

	if (button==3) {
		int level=Tweak::debug_select_level_i();
		while (selected.top().level_>level&&selected.empty()==false) {
			selected.pop();
		}
	}
	if (!selected.empty()) {
		C3f p=selected.top().get_pos();
		std::cout << "selected: " << p << "  level " << selected.top().level_ << "  " << selected.get_current() << "    " << (int)selected.get_current()->get_material() << std::endl;
	}
}




void Map2::debug() {
	std::cout << std::endl;
	std::cout << "debug " << &block << "  " << selected.top().get_current() << std::endl;
	Debugger::debug(&block,selected.top().get_current(),Tweak::draw_all_i()==1);
}

void Map2::draw() {
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_NORMALIZE);

	glPushMatrix();
	float scale=Tweak::blockscale_f();
	glScalef(scale,scale,scale);

	if (Tweak::debugdraw_i()) {
		Painter3::paint(&block,selected.top().get_current(),Tweak::draw_all_i()==1);
	} else {
		Painter6::paint(&block);
	}

	glPopMatrix();
	glDisable(GL_COLOR_MATERIAL);
}


bool Map2::does_collide(C3f p,float size) {
	return Collider::collide(&block,p,size);
}

unsigned int Map2::destroy(C3f p,float radius) {
	Destructor d;
	d.destruct(&block,p,radius);
	return d.result();
}

void Map2::set_material() {
	if (Tweak::editmode_i()!=1) return;
	int m;
	m=Tweak::material_current_i();

	Block *sel;
	sel=selected.get_current();
	if (!sel) return;
	sel->set_material(static_cast<E_Material>(m));
}

void Map2::cycle_material() {
	if (Tweak::editmode_i()!=1) return;
	E_Material mat;
	Block *sel;
	sel=selected.get_current();
	if (!sel) return;
	sel->toggle();

	mat=sel->get_material();

	unsigned int i=static_cast<unsigned int>(mat);
	i++;
	if (i<static_cast<unsigned int>(M_DEFAULT)) { 
		i=static_cast<unsigned int>(M_DEFAULT);
	}
	if (i>=static_cast<unsigned int>(M_LASTNORMAL)) { 
		i=static_cast<unsigned int>(M_DEFAULT);
	}
	std::cout << "cycle: " << (int)mat << "  " << i << std::endl;
	sel->set_material(static_cast<E_Material>(i));
}

void Map2::toggle_selected() {
	if (Tweak::editmode_i()!=1) return;
	Block *sel;
	sel=selected.get_current();
	if (!sel) return;
	sel->toggle();
}
void Map2::split_selected() {
	if (Tweak::editmode_i()!=1) return;
	Block *sel;
	sel=selected.get_current();
	if (!sel) return;
	sel->split();
}
void Map2::merge_selected() {
	if (Tweak::editmode_i()!=1) return;
	selected.pop();
	Block *sel;
	sel=selected.get_current();
	if (!sel) return;
	sel->merge();
}

void Map2::select_parent() {
	if (Tweak::editmode_i()!=1) return;
	selected.pop();
}




void Map2::check() {
	Merger::merge(&block);
}



void Map2::load(std::string name) {
	if (!block.top_load(path+name)) {
		std::cout << "error " << path <<" " << name << std::endl;
	}
	std::cout << " loaded " << name << std::endl;
	Cacher c;
	c.cache(&block,3);
}
void Map2::save() {
	std::ostringstream str;
	str << "backup/save_" << time(NULL);
	if (!block.top_save("save")) { std::cout << "error " << std::endl; }
	if (!block.top_save(str.str())) { std::cout << "error " << std::endl; }
	std::cout << " saved " << std::endl;
}


void Map2::copy() {
	std::ostringstream sstr;
	selected.top().get_current()->save(sstr);
	copystring=sstr.str();
	std::cout << "copy: " << copystring << std::endl;
}

void Map2::paste() {
	std::istringstream sstr;
	sstr.str(copystring);
	selected.top().get_current()->load(sstr);
	std::cout << "paste: " << copystring << std::endl;
}
} //namespace
