package speiger.src.coreengine.platform.input.window;

import java.util.List;

import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;

import speiger.src.collections.longs.maps.impl.hash.Long2ObjectLinkedOpenHashMap;
import speiger.src.collections.longs.maps.interfaces.Long2ObjectMap;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList;

public class Monitor
{
	final long id;
	ObjectList<VideoMode> modes = new ObjectArrayList<>();
	VideoMode defaultMode;
	int xOffset;
	int yOffset;
	
	public Monitor(long id) {
		this.id = id;
		GLFWVidMode.Buffer buffer = GLFW.glfwGetVideoModes(id);
		for(int i = buffer.limit() - 1;i >= 0;--i) {
			VideoMode videomode = new VideoMode(buffer.position(i));
			if(videomode.redBits() >= 8 && videomode.greenBits() >= 8 && videomode.blueBits() >= 8)
				modes.add(videomode);
		}
		defaultMode = new VideoMode(GLFW.glfwGetVideoMode(id));
		int[] xPos = new int[1];
		int[] yPos = new int[1];
		GLFW.glfwGetMonitorPos(id, xPos, yPos);
		xOffset = xPos[0];
		yOffset = yPos[0];
	}
	
	//@formatter:off
	public long id() { return id; }
	public String name() { return GLFW.glfwGetMonitorName(id); }
	public int size() { return modes.size(); }
	public VideoMode getMode(int index) { return modes.get(index); }
	public boolean has(VideoMode mode) { return modes.indexOf(mode) != -1; }
	public List<VideoMode> videoModes() { return modes.unmodifiable(); }
	public VideoMode defaultMode() { return defaultMode; }
	public int xOffset() { return xOffset; }
	public int yOffset() { return yOffset; }
	//@formatter:on
	
	public int getOverlap(int minX, int minY, int maxX, int maxY) {
		int x = Math.max(0, Math.clamp(maxX, xOffset, xOffset + defaultMode.width()) - Math.clamp(minX, xOffset, xOffset + defaultMode.width()));
		int y = Math.max(0, Math.clamp(maxY, yOffset, yOffset + defaultMode.height()) - Math.clamp(minY, yOffset, yOffset + defaultMode.height()));
		return x * y;
	}
	
	@Override
	public boolean equals(Object obj) { return obj instanceof Monitor mon && mon.id == id; }
	@Override
	public int hashCode() { return Long.hashCode(id); }
	@Override
	public String toString() { return "Monitor[Name=\""+name()+"\", Id="+id+", Width="+defaultMode.width()+", Height="+defaultMode.height()+", Modes="+size()+"]"; }
	
	
	public static Long2ObjectMap<Monitor> createMonitors() {
		Long2ObjectMap<Monitor> monitors = new Long2ObjectLinkedOpenHashMap<>();
		PointerBuffer buffer = GLFW.glfwGetMonitors();
		for(int i = 0,m=buffer.limit();i<m;i++) {
			long id = buffer.get();
			monitors.put(id, new Monitor(id));
		}
		return monitors;
	}
}
