#pragma once

#include "vec2.h"

template <typename T>
struct rect {
	vec2<T> pos, size;

	rect() : pos(vec2<T>::zero), size(vec2<T>::zero) {};
	rect(vec2<T> pos, vec2<T> size) : pos(pos), size(size) {};

	rect<T> normal() const; //flip direction so size is positive
	vec2<T> pos2() const;

	bool operator==(rect<T> const& other) const;

	static rect<T> from_points(vec2<T> pos1, vec2<T> pos2);
	static rect<T> intersection(rect<T> const& a, rect<T> const& b);
	static bool overlap(rect<T> const& a, rect<T> const& b);
};

template<typename T>
inline rect<T> rect<T>::normal() const {
	auto r = *this;
	if(r.size.x < 0) {
		r.pos.x += r.size.x;
		r.size.x *= -1;
	}
	if(r.size.y < 0) {
		r.pos.y += r.size.y;
		r.size.y *= -1;
	}
	return r;
}

template<typename T>
inline vec2<T> rect<T>::pos2() const {
	return pos + size - vec2<T>::one;
}

template<typename T>
inline bool rect<T>::operator==(rect<T> const& other) const {
	return pos == other.pos && size == other.size;
}

template<typename T>
inline rect<T> rect<T>::from_points(vec2<T> pos1, vec2<T> pos2) {
	return rect<T>(pos1, pos2-pos1+vec2<T>::one).normal();
}

template<typename T>
inline rect<T> rect<T>::intersection(rect<T> const& a, rect<T> const& b) {
	if(rect<T>::overlap(a, b))
		return rect<T>::from_points(vec2<T>::max(a.pos, b.pos), vec2<T>::min(a.pos2(), b.pos2()));
	return rect<T>(vec2<T>(), vec2<T>());
}

template<typename T>
inline bool rect<T>::overlap(rect<T> const& a, rect<T> const& b) {
	auto a1 = a.pos;
	auto a2 = a.pos2();
	auto b1 = b.pos;
	auto b2 = b.pos2();
	return !(b2.x < a1.x || a2.x < b1.x || b2.y < a1.y || a2.y < b1.y);
}

using recti = rect<int32_t>;
using rectf = rect<float>;
