#pragma once

#include "Types.hpp"
#include "MathF.hpp"
#include <functional>

namespace TSE
{
    class Vector2;
    class Vector3;
    class Vector4;

    class Vector2i
    {
        public:
        #pragma region members
        int x = 0, y = 0;
        #pragma endregion members

        #pragma region consts
        static const Vector2i left;
        static const Vector2i right;
        static const Vector2i up;
        static const Vector2i down;
        static const Vector2i one;
        static const Vector2i zero;
        #pragma endregion

        #pragma region ctor
        /// @brief enpty constructor defined as (0,0)
        Vector2i();
        /// @brief constructs a Vector2i with custom values
        /// @param _x the x component
        /// @param _y the y component
        Vector2i(int _x, int _y);
        /// @brief copy constructor
        /// @param other the Vector2i to be copied from
        Vector2i(const Vector2i& other);
        /// @brief copy constructor
        /// @param other the Vector2i to be copied from
        Vector2i(const Vector2& other);
        /// @brief converter constructor. it converts a Vector3 to a Vector2i without encointing for the z component
        /// @param other the Vector3 to convert
        Vector2i(const Vector3& other);
        /// @brief converter constructor. it converts a Vector4 to a Vector2i without encointing for the z, and w component
        /// @param other the Vector4 to convert
        Vector2i(const Vector4& other);
        #pragma endregion ctor

        #pragma region methods
        /// @brief checks if the individual components have valid values aka are not nan
        /// @return are the values valid
        bool IsValid() const;
        /// @brief gives you the Vector2i as a string representation. mostly for debugging
        /// @return the Vector2i in a format like (x|y)
        string ToString() const;
        /// @brief creates a Vector3 with the same values as the Vector2i, the y component gets the value 0
        /// @return the Vector2i as a Vector3
        Vector2 ToVector2() const;
        /// @brief creates a Vector3 with the same values as the Vector2i, the y component gets the value 0
        /// @return the Vector2i as a Vector3
        Vector3 ToVector3() const;
        /// @brief creates a Vector4 with the same values as the Vector2i, the y and w components get the value 0
        /// @return the Vector2i as a Vector4
        Vector4 ToVector4() const;

        #pragma region operators
        Vector2i operator+(const Vector2i& other) const;
        Vector2i operator+=(const Vector2i& other);
        Vector2i operator-(const Vector2i& other) const;
        Vector2i operator-=(const Vector2i& other);
        Vector2i operator*(const Vector2i& other) const;
        Vector2i operator*=(const Vector2i& other);
        Vector2i operator/(const Vector2i& other) const;
        Vector2i operator/=(const Vector2i& other);
        Vector2i operator*(const float other) const;
        Vector2i operator*=(const float other);
        Vector2i operator/(const float other) const;
        Vector2i operator/=(const float other);
        bool operator==(const Vector2i& other) const;
        bool operator!=(const Vector2i& other) const;
        #pragma endregion operators
        #pragma endregion methods
    };
} // namespace TSE