package speiger.src.coreengine.rendering.inputOld;

import speiger.src.coreengine.math.vector.floats.Vec3f;
import speiger.src.coreengine.math.vector.floats.Vec4f;
import speiger.src.coreengine.math.vector.ints.Vec2i;
import speiger.src.coreengine.math.vector.matrix.Matrix4f;
import speiger.src.coreengine.rendering.inputOld.camera.Camera;
import speiger.src.coreengine.rendering.inputOld.raycast.Ray;
import speiger.src.coreengine.rendering.inputOld.window.IWindowListener;
import speiger.src.coreengine.rendering.inputOld.window.Window;

public class MouseRay implements IWindowListener
{
	final static Vec2i INVALID = Vec2i.MINUS_ONE;
	final static Vec3f INVALID_3D = Vec3f.MINUS_ONE;
	Camera cam;
	Matrix4f windowMatrix;
	Vec2i windowBounds = Vec2i.mutable();
	Vec3f direction = Vec3f.of();
	Vec4f helper = Vec4f.mutable();

	public MouseRay(Camera cam, Window window)
	{
		this.cam = cam;
		window.addListener(this, true);
	}

	@Override
	public void onWindowChanged(Window window)
	{
		windowMatrix = window.getInvertedProjectionMatrix();
		windowBounds.set(window.getWidth(), window.getHeight());
	}
	
	public void update()
	{
		if(Mouse.isActive())
		{
			direction = calculateMouseRay();
		}
		else
		{
			direction = Vec3f.ZERO;
		}
	}
	
	public Vec3f getDirection()
	{
		return direction;
	}
	
	public Ray getRayCast(float maxReach)
	{
		return new Ray(cam.getPosition(), cam.getPosition().asImmutable().add(direction.x() * maxReach, direction.y() * maxReach, direction.z() * maxReach));
	}
	
//	private int[] createViewPort()
//	{
//		return GLUtils.VIEW_PORT.getCurrent().asArray();
//	}
//	
//	private Vec3f calculateWindowRay()
//	{
//		int[] viewPort = createViewPort();
//		Matrix4f mat = GameManager.INSTANCE.getProjectionBuffer().getProViewMatrix();
//		return mat.unproject(Mouse.getX(), viewPort[3] - Mouse.getY(), 1F, viewPort, Vec3f.newMutable()).sub(mat.unproject(Mouse.getX(), viewPort[3] - Mouse.getY(), 0F, viewPort, Vec3f.newMutable())).normalize();
//	}
	
	private Vec3f calculateMouseRay()
	{
		helper.set(2F * Mouse.getX() / windowBounds.x() - 1.0f, 1F - 2F * Mouse.getY() / windowBounds.y(), -1F, 1F);
		helper.transform(windowMatrix).z(-1F).w(0F).transform(cam.getInvertedViewMatrix());
		return Vec3f.of(helper.x(), helper.y(), helper.z()).normalize();		
	}
}
