/*
 * Copyright 2015 - 2025 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#if __has_include(<imgui.h>)
#include <imgui.h>
#endif

#include <ox/std/concepts.hpp>
#include <ox/std/def.hpp>
#include <ox/std/error.hpp>
#include <ox/std/types.hpp>

namespace ox {

class Vec2 {
	public:
		using value_type = float;
		using size_type = std::size_t;

		static constexpr auto TypeName = "net.drinkingtea.ox.Point";
		static constexpr auto TypeVersion = 1;

		float x = 0;
		float y = 0;

		constexpr Vec2() noexcept = default;

		explicit constexpr Vec2(class Point const&pt) noexcept;

		explicit constexpr Vec2(class Size const&pt) noexcept;

		template<typename ...Args>
		constexpr Vec2(float pX, float pY) noexcept: x(pX), y(pY) {
		}

#if __has_include(<imgui.h>)
		explicit constexpr Vec2(const ImVec2 &v) noexcept: Vec2(v.x, v.y) {
		}

		explicit inline operator ImVec2() const noexcept {
			return {x, y};
		}
#endif

		constexpr auto operator==(const Vec2 &v) const noexcept {
			return x == v.x && y == v.y;
		}

		constexpr auto operator!=(const Vec2 &v) const noexcept {
			return !operator==(v);
		}

		constexpr Vec2 operator+(float i) const noexcept {
			return {x + i, y + i};
		}

		constexpr Vec2 operator+=(float i) noexcept {
			x += i;
			y += i;
			return *this;
		}

		constexpr Vec2 operator-(float i) const noexcept {
			return {x - i, y - i};
		}

		constexpr Vec2 operator-=(float i) noexcept {
			x -= i;
			y -= i;
			return *this;
		}

		constexpr Vec2 operator*(float i) const noexcept {
			return {x * i, y * i};
		}

		constexpr Vec2 operator*=(float i) noexcept {
			x *= i;
			y *= i;
			return *this;
		}

		constexpr Vec2 operator/(float i) const noexcept {
			return {x / i, y / i};
		}

		constexpr Vec2 operator/=(float i) noexcept {
			x /= i;
			y /= i;
			return *this;
		}
};

template<typename T>
constexpr Error model(T *io, ox::CommonPtrWith<Vec2> auto *obj) noexcept {
	OX_RETURN_ERROR(io->template setTypeInfo<Vec2>());
	OX_RETURN_ERROR(io->field("x", &obj->x));
	OX_RETURN_ERROR(io->field("y", &obj->y));
	return {};
}

}
