/*
 * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
 */

#pragma once

#include <ox/model/def.hpp>
#include <ox/std/error.hpp>

namespace nostalgia::geo {

class Point {
	public:
		static constexpr auto TypeName = "net.drinkingtea.nostalgia.geo.Point";
		static constexpr auto TypeVersion = 1;
		int x = 0;
		int y = 0;

		constexpr Point() noexcept = default;

		constexpr Point(int x, int y) noexcept;

		constexpr Point operator+(const geo::Point &p) const noexcept;

		constexpr Point operator-(const geo::Point &p) const noexcept;

		constexpr Point operator*(const geo::Point &p) const noexcept;

		constexpr Point operator/(const geo::Point &p) const noexcept;


		constexpr Point operator+=(const geo::Point &p) noexcept;

		constexpr Point operator-=(const geo::Point &p) noexcept;

		constexpr Point operator*=(const geo::Point &p) noexcept;

		constexpr Point operator/=(const geo::Point &p) noexcept;


		constexpr Point operator+(int i) const noexcept;

		constexpr Point operator-(int i) const noexcept;

		constexpr Point operator*(int i) const noexcept;

		constexpr Point operator/(int i) const noexcept;


		constexpr Point operator+=(int i) noexcept;

		constexpr Point operator-=(int i) noexcept;

		constexpr Point operator*=(int i) noexcept;

		constexpr Point operator/=(int i) noexcept;


		constexpr bool operator==(const Point&) const noexcept;

		constexpr bool operator!=(const Point&) const noexcept;

};

constexpr Point::Point(int x, int y) noexcept {
	this->x = x;
	this->y = y;
}

constexpr Point Point::operator+(const geo::Point &p) const noexcept {
	auto out = *this;
	out.x += p.x;
	out.y += p.y;
	return out;
}

constexpr Point Point::operator-(const geo::Point &p) const noexcept {
	auto out = *this;
	out.x -= p.x;
	out.y -= p.y;
	return out;
}

constexpr Point Point::operator*(const geo::Point &p) const noexcept {
	auto out = *this;
	out.x *= p.x;
	out.y *= p.y;
	return out;
}

constexpr Point Point::operator/(const geo::Point &p) const noexcept {
	auto out = *this;
	out.x /= p.x;
	out.y /= p.y;
	return out;
}

constexpr Point Point::operator+=(const geo::Point &p) noexcept {
	x += p.x;
	y += p.y;
	return *this;
}

constexpr Point Point::operator-=(const geo::Point &p) noexcept {
	x -= p.x;
	y -= p.y;
	return *this;
}

constexpr Point Point::operator*=(const geo::Point &p) noexcept {
	x *= p.x;
	y *= p.y;
	return *this;
}

constexpr Point Point::operator/=(const geo::Point &p) noexcept {
	x /= p.x;
	y /= p.y;
	return *this;
}


constexpr Point Point::operator+(int i) const noexcept {
	auto out = *this;
	out.x += i;
	out.y += i;
	return out;
}

constexpr Point Point::operator-(int i) const noexcept {
	auto out = *this;
	out.x -= i;
	out.y -= i;
	return out;
}

constexpr Point Point::operator*(int i) const noexcept {
	auto out = *this;
	out.x *= i;
	out.y *= i;
	return out;
}

constexpr Point Point::operator/(int i) const noexcept {
	auto out = *this;
	out.x /= i;
	out.y /= i;
	return out;
}

constexpr Point Point::operator+=(int i) noexcept {
	x += i;
	y += i;
	return *this;
}

constexpr Point Point::operator-=(int i) noexcept {
	x -= i;
	y -= i;
	return *this;
}

constexpr Point Point::operator*=(int i) noexcept {
	x *= i;
	y *= i;
	return *this;
}

constexpr Point Point::operator/=(int i) noexcept {
	x /= i;
	y /= i;
	return *this;
}

constexpr bool Point::operator==(const Point &p) const noexcept {
	return x == p.x && y == p.y;
}

constexpr bool Point::operator!=(const Point &p) const noexcept {
	return x != p.x || y != p.y;
}

oxModelBegin(Point)
	oxModelField(x)
	oxModelField(y)
oxModelEnd()

}
