#ifndef PREDICTION_HPP
#define PREDICTION_HPP

#define RAD2DEG(x) ((float)(x) * (float)(180.f / std::numbers::pi))

using namespace enums;

namespace prediction
{
	struct weapon_data_map
	{
		float         bullet_speed;
		float         bullet_scale;

		int			  magazine_size;
		float		  reload_time;

		bool operator<( const weapon_data_map& other ) const
		{
			if ( bullet_speed != other.bullet_speed )
				return bullet_speed < other.bullet_speed;
			if ( bullet_scale != other.bullet_scale )
				return bullet_scale < other.bullet_scale;
			if ( magazine_size != other.magazine_size )
				return magazine_size < other.magazine_size;
			if ( reload_time != other.reload_time )
				return reload_time < other.reload_time;
		}
	};

	struct prediction_context
	{
		float                        distance;
		math::vector3                position;
		math::vector3                player_velocity;
		EFortWeaponCoreAnimation     animation_type;
		weapon_data_map              weapon_data_map;
	};

	class c_prediction
	{
	public:
		std::multimap<weapon_data_map, std::string> weapon_map;

		explicit c_prediction();

		[[nodiscard]] weapon_data_map get_weapon_data( const std::string& weapon );

		[[nodiscard]] bool is_sniper( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::SniperRifle:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_shotgun( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::Shotgun:
				case EFortWeaponCoreAnimation::TacticalShotgun:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_rifle( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::AssaultRifle:
				case EFortWeaponCoreAnimation::Rifle:
				case EFortWeaponCoreAnimation::AR_DrumGun:
				case EFortWeaponCoreAnimation::AR_ForwardGrip:
				case EFortWeaponCoreAnimation::AR_BullPup:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_pistol( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::MachinePistol:
				case EFortWeaponCoreAnimation::Pistol:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_smg( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::SMG_P90:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_consumable( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::Consumable_Small:
				case EFortWeaponCoreAnimation::MeleeDualWield:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_other( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {

				case EFortWeaponCoreAnimation::ExplosiveBow:
				case EFortWeaponCoreAnimation::MountedTurret:
				case EFortWeaponCoreAnimation::RocketLauncher:
				case EFortWeaponCoreAnimation::GrenadeLauncher:
				case EFortWeaponCoreAnimation::Melee:
				case EFortWeaponCoreAnimation::TrapPlacement:
				case EFortWeaponCoreAnimation::PaperBlueprint:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] bool is_weapon( prediction_context& ctx ) {
			switch ( ctx.animation_type ) {
				case EFortWeaponCoreAnimation::Melee:
				case EFortWeaponCoreAnimation::Consumable_Small:
				case EFortWeaponCoreAnimation::MeleeDualWield:
				case EFortWeaponCoreAnimation::TrapPlacement:
				case EFortWeaponCoreAnimation::PaperBlueprint:
					return false;

				case EFortWeaponCoreAnimation::AssaultRifle:
				case EFortWeaponCoreAnimation::Pistol:
				case EFortWeaponCoreAnimation::SMG_P90:
				case EFortWeaponCoreAnimation::Crossbow:
				case EFortWeaponCoreAnimation::Rifle:
				case EFortWeaponCoreAnimation::AR_DrumGun:
				case EFortWeaponCoreAnimation::AR_ForwardGrip:
				case EFortWeaponCoreAnimation::AR_BullPup:
				case EFortWeaponCoreAnimation::GrenadeLauncher:
				case EFortWeaponCoreAnimation::RocketLauncher:
				case EFortWeaponCoreAnimation::MachinePistol:
				case EFortWeaponCoreAnimation::MountedTurret:
				case EFortWeaponCoreAnimation::ExplosiveBow:
				case EFortWeaponCoreAnimation::Shotgun:
				case EFortWeaponCoreAnimation::TacticalShotgun:
				case EFortWeaponCoreAnimation::SniperRifle:
					return true;

				default:
					return false;
			}
		}

		[[nodiscard]] math::vector3 resolve_position(
			prediction_context& ctx
		);
	};
}
inline auto g_prediction = std::make_shared<prediction::c_prediction>();

#endif // !PREDICTION_HPP