class TimeToReachCalculator {
public:
	static float calculateTimeToReach(const PlayerData& player, const Vec& targetPos) {
		Vec carPos = player.phys.pos;
		Vec carVel = player.phys.vel;
		Vec dirToTarget = (targetPos - carPos).Normalized();
		float dist = (targetPos - carPos).Length() - CommonValues::BALL_RADIUS;
		float vel = carVel.Dot(dirToTarget);
		float rotTime = calculateRotationTime(player, targetPos);
		float timeToSurface = calculateTimeToReachAnySurface(player);

		float t = 0;
		for (float curDist = dist, curVel = vel; curDist > DIST_REACH_THRESH; t += STEP_INTERVAL, curDist -= curVel * STEP_INTERVAL) {
			bool hasRotated = t >= rotTime;
			bool onSurface = t >= timeToSurface;

			if (curVel < MAX_TOTAL_SPEED && t == 0) {
				// Flip force
				curVel += FLIP_FORCE;
			}

			if (onSurface) {
				if (curVel < 0) {
					curVel += (BRAKE_ACCEL + BOOST_ACCEL_GROUND * hasRotated) * STEP_INTERVAL;
				}
				else if (curVel < MAX_DRIVE_SPEED) {
					curVel += (DRIVE_ACCEL + BOOST_ACCEL_GROUND * hasRotated) * STEP_INTERVAL;
				}
				else if (curVel < MAX_TOTAL_SPEED) {
					curVel += BOOST_ACCEL_GROUND * hasRotated * STEP_INTERVAL;
				}
			}

			if (curVel >= MAX_TOTAL_SPEED) {
				return t + (curDist / curVel);
			}
		}
		return t;
	}

private:


	// Constants related to the arena dimensions
	float SIDE_WALL_X = 4096.0f;
	constexpr float CLOSE_DISTANCE = 10.0f;        // Distance threshold for proximity to the walls
	constexpr float NEAR_WALL_DISTANCE = 4077.0f;  // Threshold for x close to the wall
	constexpr float Z_THRESHOLD = 256.0f;          // Threshold for z axis proximity to the ground
	constexpr float EPSILON = 1e-3f;               // Small value for floating point comparison

	// Movement-related constants
	constexpr float DIST_REACH_THRESH = 80.0f;
	constexpr float STEP_INTERVAL = 1.0f / 60.0f;    // Time step (e.g., 60 FPS)
	constexpr float FLIP_FORCE = 495.0f;
	constexpr float AIR_ACCEL = 66.66667f;
	constexpr float BOOST_ACCEL_AIR = 1058.33333f;
	constexpr float MAX_TOTAL_SPEED = 2300.0f;
	constexpr float BRAKE_ACCEL = 3500.0f;
	constexpr float BOOST_ACCEL_GROUND = 991.66667f;
	constexpr float DRIVE_ACCEL = 1600.0f;
	constexpr float MAX_DRIVE_SPEED = 1410.0f;
	constexpr float GRAVITY_Z = -650.0f; // Example gravity value, adjust as needed

	// Constants related to the arena dimensions
	constexpr float BACK_WALL_Y = 5120.0f;
	constexpr float NEG_BACK_WALL_Y = -5120.0f;     // Negative back wall at y = -5120.0f
	constexpr float MAX_BACKWALL_Y = 5100.0f;       // New threshold as per user request
	constexpr float BOOST_ACCEL_POS = 1000.0f;      // Boost acceleration towards positive back wall (units/s²)
	constexpr float BOOST_ACCEL_NEG = -1000.0f;     // Boost acceleration towards negative back wall (units/s²)

	// Constants related to the arena dimensions and gravity
	constexpr float FLOOR_Z = 18.0f;      // Assuming the floor is at z = 0
	constexpr float BOOST_ACCEL_DOWN = -1000.0f;

	static float calculateTimeToSideWalls(const PlayerData& player) {
		const Vec& pos = player.phys.pos;
		const Vec& vel = player.phys.vel;

		float minTime = std::numeric_limits<float>::infinity();

		if (std::abs(pos.x) >= NEAR_WALL_DISTANCE && std::abs(pos.x) <= SIDE_WALL_X) {
			return 0.0f;
		}

		if (vel.x > EPSILON) {
			float a = 0.5f * DRIVE_ACCEL;
			float b = vel.x;
			float c = pos.x - SIDE_WALL_X;

			float discriminant = b * b - 4.0f * a * c;

			if (discriminant >= 0.0f) {
				float sqrtD = std::sqrt(discriminant);
				float t1 = (-b + sqrtD) / (2.0f * a);
				float t2 = (-b - sqrtD) / (2.0f * a);

				if (t1 > EPSILON && t1 < minTime) {
					minTime = t1;
				}
				if (t2 > EPSILON && t2 < minTime) {
					minTime = t2;
				}
			}
		}

		if (vel.x < -EPSILON) {
			float a = 0.5f * (-DRIVE_ACCEL);
			float b = vel.x;
			float c = pos.x + SIDE_WALL_X;

			float discriminant = b * b - 4.0f * a * c;

			if (discriminant >= 0.0f) {
				float sqrtD = std::sqrt(discriminant);
				float t1 = (-b + sqrtD) / (2.0f * a);
				float t2 = (-b - sqrtD) / (2.0f * a);

				if (t1 > EPSILON && t1 < minTime) {
					minTime = t1;
				}
				if (t2 > EPSILON && t2 < minTime) {
					minTime = t2;
				}
			}
		}

		return minTime;
	}

	static float calculateTimeToBackWalls(const PlayerData& player) {
		const Vec& pos = player.phys.pos;
		const Vec& vel = player.phys.vel;

		float minTime = std::numeric_limits<float>::infinity();

		if (pos.y >= MAX_BACKWALL_Y || pos.y <= -MAX_BACKWALL_Y) {
			return 0.0f;
		}

		if (pos.y >= BACK_WALL_Y || pos.y <= NEG_BACK_WALL_Y) {
			return 0.0f;
		}

		if (vel.y > EPSILON) {
			float a = 0.5f * BOOST_ACCEL_POS;
			float b = vel.y;
			float c = pos.y - BACK_WALL_Y;

			float discriminant = b * b - 4.0f * a * c;

			if (discriminant >= 0.0f) {
				float sqrtD = std::sqrt(discriminant);
				float t1 = (-b + sqrtD) / (2.0f * a);
				float t2 = (-b - sqrtD) / (2.0f * a);

				if (t1 > EPSILON && t1 < minTime) {
					minTime = t1;
				}
				if (t2 > EPSILON && t2 < minTime) {
					minTime = t2;
				}
			}
		}

		if (vel.y < -EPSILON) {
			float a = 0.5f * BOOST_ACCEL_NEG;
			float b = vel.y;
			float c = pos.y - NEG_BACK_WALL_Y;

			float discriminant = b * b - 4.0f * a * c;

			if (discriminant >= 0.0f) {
				float sqrtD = std::sqrt(discriminant);
				float t1 = (-b + sqrtD) / (2.0f * a);
				float t2 = (-b - sqrtD) / (2.0f * a);

				if (t1 > EPSILON && t1 < minTime) {
					minTime = t1;
				}
				if (t2 > EPSILON && t2 < minTime) {
					minTime = t2;
				}
			}
		}

		return minTime;
	}

	static float calculateTimeToFloor(const PlayerData& player) {
		const Vec& pos = player.phys.pos;
		const Vec& vel = player.phys.vel;

		if (pos.z <= FLOOR_Z) {
			return 0.0f;
		}

		float totalAccel = GRAVITY_Z + BOOST_ACCEL_DOWN;

		float a = 0.5f * totalAccel;
		float b = vel.z;
		float c = pos.z - FLOOR_Z;

		float discriminant = b * b - 4.0f * a * c;

		if (discriminant < 0.0f) {
			return std::numeric_limits<float>::infinity();
		}

		float sqrtD = std::sqrt(discriminant);
		float t1 = (-b - sqrtD) / (2.0f * a);
		float t2 = (-b + sqrtD) / (2.0f * a);

		float timeToFloor = std::numeric_limits<float>::infinity();

		if (t1 > 0.0f) {
			timeToFloor = t1;
		}
		if (t2 > 0.0f && t2 < timeToFloor) {
			timeToFloor = t2;
		}

		return timeToFloor;
	}

	static float calculateTimeToReachAnySurface(const PlayerData& player) {
		float timeToSideWalls = calculateTimeToSideWalls(player);
		float timeToBackWalls = calculateTimeToBackWalls(player);
		float timeToFloor = calculateTimeToFloor(player);

		float minTimeBetweenBackWallsAndFloor = RS_MIN(timeToBackWalls, timeToFloor);
		float minTime = RS_MIN(timeToSideWalls, minTimeBetweenBackWallsAndFloor);

		return minTime;
	}

	static float calculateRotationTime(const PlayerData& player, const Vec& targetPos) {
		constexpr float MAX_ANG_VEL = 5.5f * 0.9f;

		Vec playerPos = player.phys.pos;
		Vec playerForward = player.phys.rotMat.forward;
		Vec dirToTarget = (targetPos - playerPos).Normalized();
		float angleDiff = std::acos(RS_CLAMP(playerForward.Dot(dirToTarget), -1.0f, 1.0f));

		return angleDiff / MAX_ANG_VEL;
	}
}; make al the dinfinition not contrexpt and make everything be defined and correct