#include "vectorimage.h"
#include "splines.h"


void VectorImage::Stroke::Add(const Vector2D &p) {
	points.push_back(p);
}


void VectorImage::Stroke::SetPoint(int i, const Vector2D &p) {
	points[i] = p;
}


void VectorImage::Stroke::Remove(const Vector2D &p, float bias) {
	int which = Find(p);
	if (which >= 0) {
		std::vector<Vector2D>::iterator iter = points.begin();
		for (int i=0; i<which; i++, ++iter);
		points.erase(iter);
	}
}


int VectorImage::Stroke::Find(const Vector2D &p, float bias) {
	for (int i=0; i<points.size(); i++) {
		if (points[i].Distance(p) <= bias) {
			return i;
		}
	}

	return -1;
}


int VectorImage::Stroke::GetLength() {
	return points.size();
}


const Vector2D& VectorImage::Stroke::GetPoint(int i) {
	return points[i];
}


void VectorImage::Stroke::SetColour(int c) {
	colour = c;
}


int VectorImage::Stroke::GetColour() {
	return colour;
}


void VectorImage::Stroke::Move(const Vector2D &d) {
	for (int i=0; i<points.size(); i++) {
		points[i] += d;
	}
}


void VectorImage::Stroke::SetFlag(int f, bool on) {
	if (on) {
		flags |= f;
	}
	else {
		flags &= ~f;
	}
}


bool VectorImage::Stroke::TestFlag(int f) {
	return (flags & f);
}


void VectorImage::Stroke::SetThickness(float t) {
	thickness = t;
}


float VectorImage::Stroke::GetThickness() {
	return thickness;
}


void VectorImage::Stroke::SetCurviness(float c) {
	curviness = c;
}


float VectorImage::Stroke::GetCurviness() {
	return curviness;
}


void VectorImage::Stroke::Render(BITMAP *canvas, float zoom, int offset_x, int offset_y, int mode, bool debug) {
	if (points.empty()) return;

	float w = canvas->w * zoom;
	float h = canvas->h * zoom;

	if (!debug) {
		float line_w = w*thickness;

		std::vector<Vector2D> p2;
		for (int i=0; i<points.size(); i++) {
			p2.push_back(Vector2D(w*points[i].x() - offset_x, h*points[i].y() - offset_y));
		}

		if (mode & VGFX_STROKES) {
			draw_aa_splines(canvas, p2, curviness, line_w, colour, 2.0f, TestFlag(VGFX_CLOSE_PATH), flags);
		}
		else {
			draw_splines(canvas, p2, curviness, colour, TestFlag(VGFX_CLOSE_PATH));
		}

		p2.clear();

		/*
		Vector2D last = points[0];

		if (mode & VGFX_STROKES) {
			for (int i=1; i<points.size(); i++) {
				Vector2D p = points[i];
				aa_line(canvas, (int)(w*last.x()) - offset_x, (int)(h*last.y()) - offset_y, (int)(w*p.x()) - offset_x, (int)(h*p.y()) - offset_y, line_w, colour, 2.0f);
				last = p;
			}
		}
		else {
			for (int i=1; i<points.size(); i++) {
				Vector2D p = points[i];
				line(canvas, (int)(w*last.x()) - offset_x, (int)(h*last.y()) - offset_y, (int)(w*p.x()) - offset_x, (int)(h*p.y()) - offset_y, colour);
				last = p;
			}
		}
		*/
	}
	else {
		if (mode & VGFX_STROKES) {
			for (int i=0; i<points.size(); i++) {
				Vector2D p = points[i];
				circlefill(canvas, (int)(w*p.x()) - offset_x, (int)(h*p.y()) - offset_y, 4, makecol(255,255,255));
				circle(canvas, (int)(w*p.x()) - offset_x, (int)(h*p.y()) - offset_y, 4, makecol(0,0,0));
			}
		}
		else {
			for (int i=0; i<points.size(); i++) {
				Vector2D p = points[i];
				putpixel(canvas, (int)(w*p.x()) - offset_x, (int)(h*p.y()) - offset_y, makecol(255,0,0));
				circle(canvas, (int)(w*p.x()) - offset_x, (int)(h*p.y()) - offset_y, 4, makecol(0,0,0));
			}
		}
	}
}


VectorImage::Stroke::Stroke() : flags(VGFX_CAPS_BOTH), thickness(0.01f), curviness(0.3f) {
	colour = makecol(0,0,0);
}


VectorImage::Stroke::~Stroke() {
	points.clear();
}
