#pragma once
#include "../gen/Generated.h"

namespace Gen
{
    bool IsValid(const AssetHandle& h);
    bool IsValid(const ModelHandle& h);
    bool IsValid(const TextureHandle& h);

    bool operator==(const AssetHandle& lhs, const AssetHandle& rhs);
    bool operator==(const ModelHandle& lhs, const ModelHandle& rhs);

    PuzPos operator+=(PuzPos lhs, const PuzPos& rhs);
    PuzPos operator+(PuzPos lhs, const PuzPos& rhs);

    Vec4& operator+=(Vec4& lhs, const Vec4& rhs);
    Vec4 operator+(const Vec4& lhs, const Vec4& rhs);
    Vec4& operator+=(Vec4& lhs, float rhs);
    Vec4 operator+(Vec4& lhs, float rhs);

    Vec4& operator-=(Vec4& lhs, const Vec4& rhs);
    Vec4 operator-(const Vec4& lhs, const Vec4& rhs);
    Vec4& operator-=(Vec4& lhs, float rhs);
    Vec4 operator-(const Vec4& lhs, float rhs);

    Vec4& operator*=(Vec4& lhs, float rhs);
    Vec4 operator*(const Vec4& lhs, float rhs);

    Vec4& operator/=(Vec4& lhs, float rhs);
    Vec4 operator/(const Vec4& lhs, float rhs);

    Vec3& operator+=(Vec3& lhs, const Vec3& rhs);
    Vec3 operator+(const Vec3& lhs, const Vec3& rhs);
    Vec3& operator+=(Vec3& lhs, float rhs);
    Vec3 operator+(Vec3& lhs, float rhs);

    Vec3& operator-=(Vec3& lhs, const Vec3& rhs);
    Vec3 operator-(const Vec3& lhs, const Vec3& rhs);
    Vec3& operator-=(Vec3& lhs, float rhs);
    Vec3 operator-(const Vec3& lhs, float rhs);

    Vec3& operator*=(Vec3& lhs, float rhs);
    Vec3 operator*(const Vec3& lhs, float rhs);

    Vec3& operator/=(Vec3& lhs, float rhs);
    Vec3 operator/(const Vec3& lhs, float rhs);

    Vec2& operator+=(Vec2& lhs, const Vec2& rhs);
    Vec2 operator+(const Vec2& lhs, const Vec2& rhs);
    Vec2& operator+=(Vec2& lhs, float rhs);
    Vec2 operator+(Vec2& lhs, float rhs);

    Vec2& operator-=(Vec2& lhs, const Vec2& rhs);
    Vec2 operator-(const Vec2& lhs, const Vec2& rhs);
    Vec2& operator-=(Vec2& lhs, float rhs);
    Vec2 operator-(const Vec2& lhs, float rhs);

    Vec2& operator*=(Vec2& lhs, float rhs);
    Vec2 operator*(const Vec2& lhs, float rhs);

    Vec2& operator/=(Vec2& lhs, float rhs);
    Vec2 operator/(const Vec2& lhs, float rhs);

    float Magnitude(const Vec4& vec);
    float Magnitude(const Vec3& vec);
    float Magnitude(const Vec2& vec);

    Vec4 Normalized(const Vec4& vec);
    Vec3 Normalized(const Vec3& vec);
    Vec2 Normalized(const Vec2& vec);

    Mat4 Inverse(const Mat4& mat);
    Mat4 Transpose(const Mat4& mat);
    Vec4 Mul(const Mat4& mat, const Vec4& vec);

    Vec3 EulerFromRotation(const Mat4& rotation);
    Mat4 RotationFromEuler(const Vec3& euler);

    float DotProduct(Vec3 a, Vec3 b);
    Vec3 CrossProduct(Vec3 a, Vec3 b);
    Vec3 CrossProductFromPlane(Vec3 a, Vec3 b, Vec3 c);
    bool RayPlaneIntersect(Vec3 l1, Vec3 l2, Vec3 p1, Vec3 p2, Vec3 p3, Vec3& out);

    void Translate(Transform& trans, Vec3 offset);
    void TranslateLocal(Transform& trans, Vec3 offset);
    void Rotate(Transform& trans, Vec3 rotation);
    void RotateLocal(Transform& trans, Vec3 rotation);
    Vec3 LocalToGlobalPoint(Transform& trans, Vec3 local);
    Vec3 LocalToGlobalDirection(Transform& trans, Vec3 local);
    Vec3 GlobalToLocalPoint(Transform& trans, Vec3 global);
    Vec3 GlobalToLocalDirection(Transform& trans, Vec3 global);
    Vec3 AxisRight(const Mat4& mat);
    Vec3 AxisUp(const Mat4& mat);
    Vec3 AxisForward(const Mat4& mat);
    void UpdateMatrix(Transform& trans);
} // namespace Gen
