#include "wcolimage.h"
#include "wcolgradgen.h"
using namespace MAS;


void WColImage::AddAttractor() {
	WColImage::Attractor a;
	attractors.push_back(a);
}


void WColImage::RemoveAttractor(int which) {
	std::vector<WColImage::Attractor>::iterator iter = attractors.begin();
	for (int i=0; i<which; i++, ++iter);
	attractors.erase(iter);
}


WColImage::Attractor &WColImage::GetAttractor(int which) {
	return attractors[which];
}


int WColImage::GetAttractorCount() {
	return attractors.size();
}


void WColImage::Render(Bitmap &canvas) {
	col_att_list list;
	init_ca_list(&list);
	for (std::vector<Attractor>::iterator i = attractors.begin(); i != attractors.end(); ++i) {
		int type = i->type;
		int x = (int)(type == 0 ? i->x*100 : i->x*canvas.w());
		int y = (int)(i->y*canvas.h());
		int range = (int)(i->range*(canvas.w()+canvas.h())/2);
		add_to_ca_list(&list, (CA_TYPE)type, (CA_MODE)(i->mode), x, y, i->r, i->g, i->b, range, i->linearity, i->multiplier);
	}
	render_col_grad_to_bitmap(canvas, &list);
	kill_ca_list(&list);
}


int WColImage::Load(const char *filename) {
	Clear();
	PACKFILE *f = pack_fopen(filename, "r");
	if (!f) {
		return 1;
	}

	char tmp[4];
	pack_fread(tmp, 4*sizeof(char), f);
	if (ustrncmp(tmp, "WCOL", 4) != 0) {
		pack_fclose(f);
		return 2;
	}

	char vMajor = 1;
	char vMinor = 0;
	pack_fread(&vMajor, sizeof(char), f);
	pack_fread(&vMinor, sizeof(char), f);
	int fileVersion = vMajor*100+vMinor;
	int WCOL_VERSION = WCOL_VERSION_MAJOR*100 + WCOL_VERSION_MINOR;
	if (fileVersion > WCOL_VERSION || fileVersion < 100) {
		pack_fclose(f);
		return 3;
	}

	if (fileVersion >= 102) {
		static char buf[64+1];
		int l = 0;
		pack_fread(&l, sizeof(int), f);
		if (l) {
			pack_fread(buf, l*sizeof(char), f);
			buf[l] = 0;
			author = std::string(buf);
		}
		else {
			author = std::string("");
		}

		pack_fread(&l, sizeof(int), f);
		if (l) {
			pack_fread(buf, l*sizeof(char), f);
			buf[l] = 0;
			title = std::string(buf);
		}
		else {
			title = std::string("");
		}
	}
	else {
		author = std::string("");
		title = std::string("");
	}

	int n;
	pack_fread(&n, sizeof(int), f);
	for (int i=0; i<n; i++) {
		AddAttractor();
		pack_fread(&(attractors[i].type), sizeof(int), f);
		if (fileVersion >= 105) {
			pack_fread(&(attractors[i].mode), sizeof(int), f);
		}
		else {
			attractors[i].mode = 0;
		}
		pack_fread(&(attractors[i].x), sizeof(float), f);
		pack_fread(&(attractors[i].y), sizeof(float), f);
		pack_fread(&(attractors[i].range), sizeof(float), f);
		pack_fread(&(attractors[i].r), sizeof(int), f);
		pack_fread(&(attractors[i].g), sizeof(int), f);
		pack_fread(&(attractors[i].b), sizeof(int), f);
		if (fileVersion >= 103) {
			if (fileVersion >= 108) {
				pack_fread(&(attractors[i].linearity), sizeof(float), f);
			}
			else {
				int linearity;
				pack_fread(&linearity, sizeof(int), f);
				attractors[i].linearity = (float)linearity / 128.0f;
			}
		}
		else {
			attractors[i].linearity = 1.0f;
		}
		if (fileVersion >= 107) {
			pack_fread(&(attractors[i].multiplier), sizeof(float), f);
		}
		else {
			attractors[i].multiplier = 1.0f;
		}
	}

	pack_fclose(f);

	return 0;
}


int WColImage::Save(const char *filename) {
	PACKFILE *f = pack_fopen(filename, "w");
	if (!f) {
		return 1;
	}

	pack_fwrite("WCOL", 4*sizeof(char), f);
	char vMajor = WCOL_VERSION_MAJOR;
	char vMinor = WCOL_VERSION_MINOR;
	pack_fwrite(&vMajor, sizeof(char), f);
	pack_fwrite(&vMinor, sizeof(char), f);

	int l = author.size();
	pack_fwrite(&l, sizeof(int), f);
	if (l) pack_fwrite(author.c_str(), l*sizeof(char), f);
	l = title.size();
	pack_fwrite(&l, sizeof(int), f);
	if (l) pack_fwrite(title.c_str(), l*sizeof(char), f);

	int n = attractors.size();
	pack_fwrite(&n, sizeof(int), f);
	for (int i=0; i<n; i++) {
		pack_fwrite(&(attractors[i].type), sizeof(int), f);
		pack_fwrite(&(attractors[i].mode), sizeof(int), f);
		pack_fwrite(&(attractors[i].x), sizeof(float), f);
		pack_fwrite(&(attractors[i].y), sizeof(float), f);
		pack_fwrite(&(attractors[i].range), sizeof(float), f);
		pack_fwrite(&(attractors[i].r), sizeof(int), f);
		pack_fwrite(&(attractors[i].g), sizeof(int), f);
		pack_fwrite(&(attractors[i].b), sizeof(int), f);
		pack_fwrite(&(attractors[i].linearity), sizeof(float), f);
		pack_fwrite(&(attractors[i].multiplier), sizeof(float), f);
	}

	pack_fclose(f);

	return 0;
}


void WColImage::Clear() {
	attractors.clear();
}


WColImage::WColImage() {
	Clear();
}


WColImage::~WColImage() {
	Clear();
}


void WColImage::MoveAttractor(int which, int where) {
	int second = which + where;

	if (which >= 0 && which < GetAttractorCount() && second >= 0 && second < GetAttractorCount()) {
		Attractor tmp = attractors[which];
		attractors[which] = attractors[second];
		attractors[second] = tmp;
	}
}


void WColImage::DuplicateAttractor(int which) {
	if (which >= 0 && which < GetAttractorCount()) {
		attractors.push_back(attractors[which]);
	}
}


std::string &WColImage::GetAuthor() {
	return author;
}


std::string &WColImage::GetTitle() {
	return title;
}


void WColImage::SetAuthor(std::string author) {
	this->author = author;
}


void WColImage::SetTitle(std::string title) {
	this->title = title;
}
