#include <SDL2/SDL.h>

#include <assert.h>
#include <stdlib.h>

#include "maths.cpp"

struct Shape {
	v2f* points;
	int count;

	Shape(std::initializer_list<v2f> in) {
		int i;
		points = (v2f*)malloc(in.size() * sizeof *points);
		count = in.size();
		for (i = 0; i < count; i++)
			points[i] = *(in.begin() + i);
	}

	Shape(const Shape& other) {
		int s = other.count * sizeof *points;
		count = other.count;
		points = (v2f*)malloc(s);
		memcpy(points, other.points, s);
	}

	~Shape() {
		free(points);
	}

	void render(SDL_Renderer* ren) {
		int i, c = count;
		for (i = 0; i < c; i++) {
			v2f a = points[i];
			v2f b = points[(i + 1) % c];
			SDL_RenderDrawLine(
				ren,
				(int)a.x,
				(int)a.y,
				(int)b.x,
				(int)b.y
			);
		}
	}

	std::pair<v2f*, int> normals() const {
		int c = (count >> 1) + 1, i;
		v2f* normals = (v2f*)malloc(c * sizeof *normals);
		for (i = 0; i < count; i++) {
			v2f a = points[i];
			v2f b = points[(i + 1) % count];
			v2f e = a - b;
			v2f n = v2f::normalised(v2f(e.y, -e.x));
			normals[i] = n;
		}
		return { normals, i };
	}
};

bool intersect(Shape& a, Shape& b) {
	bool r = true;
	int i;
	auto[fn, fnc] = a.normals();
	auto[sn, snc] = b.normals();
	auto project = [](const Shape& shape, v2f axis) {
		int i;
		float mini =  INFINITY;
		float maxi = -INFINITY;
		for (i = 0; i < shape.count; i++) {
			v2f p = shape.points[i];
			float d = v2f::dot(p, axis);
			if (d < mini) mini = d;
			if (d > maxi) maxi = d;
		}
		return std::pair<float, float>{ mini, maxi };
	};
	for (i = 0; i < fnc; i++) {
		v2f axis = fn[i];
		auto [fp1, fp2] = project(a, axis);
		auto [sp1, sp2] = project(b, axis);
		if (fp2 > sp1 && fp1 > sp2) {
			r = false;
			goto end;
		}
	}
	for (i = 0; i < snc; i++) {
		v2f axis = sn[i];
		auto [fp1, fp2] = project(a, axis);
		auto [sp1, sp2] = project(b, axis);
		if (fp2 > sp1 && fp1 > sp2) {
			r = false;
			goto end;
		}
	}
end:
	free(fn);
	free(sn);
	return r;
}

int main(int argc, const char** argv) {
	int r = 1;
	SDL_Window* window;
	SDL_Renderer* ren;
	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
	SDL_CreateWindowAndRenderer(
		800,
		800,
		0,
		&window,
		&ren
	);
	Shape a({
		v2f(300.0f, 300.0f),
		v2f(400.0f, 400.0f),
		v2f(250.0f, 500.0f),
	});
	Shape tri({
		v2f(0.0f, 0.0f),
		v2f(50.0f, 200.0f),
		v2f(200.0f, 100.0f),
	});
	while (r) {
		int i;
		SDL_Event e;
		while (SDL_PollEvent(&e)) {
			switch (e.type) {
				case SDL_QUIT:
					r = 0;
					break;
			}
		}
		int mx, my;
		SDL_GetMouseState(&mx, &my);
		Shape b(tri);
		for (i = 0; i < b.count; i++) {
			v2f& p = b.points[i];
			p.x += mx;
			p.y += my;
		}
		SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0x00);
		SDL_RenderClear(ren);
		SDL_SetRenderDrawColor(ren, 0xff, 0x00, 0xff, 0xff);
		a.render(ren);
		if (intersect(a, b)) {
			SDL_SetRenderDrawColor(ren, 0xff, 0x00, 0x00, 0xff);
		}
		b.render(ren);
		SDL_RenderPresent(ren);
	}
	SDL_DestroyRenderer(ren);
	SDL_DestroyWindow(window);
	SDL_Quit();
	return 0;
}