package speiger.src.coreengine.rendering.utils;

import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWImage;

import speiger.src.collections.longs.utils.LongCollections;
import speiger.src.collections.objects.maps.impl.hash.Object2LongOpenHashMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
import speiger.src.collections.objects.maps.interfaces.Object2LongMap;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap.Entry;
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.reloader.IReloadableResource;
import speiger.src.coreengine.rendering.inputOld.window.Window;
import speiger.src.coreengine.rendering.texturesOld.base.TextureManager;

public final class Cursor implements IReloadableResource {
	public static final Cursor INSTANCE = new Cursor();
	public static final AssetLocation CURSOR_ARROW = AssetLocation.of("Arrow");
	public static final AssetLocation CURSOR_IBEAM = AssetLocation.of("I-Beam");
	public static final AssetLocation CURSOR_CROSSHAIR = AssetLocation.of("Crosshair");
	public static final AssetLocation CURSOR_HAND = AssetLocation.of("Hand");
	public static final AssetLocation CURSOR_HRESIZE = AssetLocation.of("H-Resize");
	public static final AssetLocation CURSOR_VRESIZE = AssetLocation.of("V-Resize");
	static final AssetLocation[] LOCATIONS = new AssetLocation[] { CURSOR_ARROW, CURSOR_IBEAM, CURSOR_CROSSHAIR, CURSOR_HAND, CURSOR_HRESIZE, CURSOR_VRESIZE };
	long currentCursor = 0;
	boolean ignore = false;
	Object2ObjectMap<AssetLocation, AssetLocation> customCursors = new Object2ObjectLinkedOpenHashMap<>();
	Object2LongMap<AssetLocation> cursors = new Object2LongOpenHashMap<>();
	
	Cursor() {}
	
	public void createCursor(AssetLocation id, AssetLocation texture) {
		GLFWImage image = TextureManager.create(texture);
		if(image != null) {
			customCursors.put(id, texture);
			cursors.put(id, GLFW.glfwCreateCursor(image, 0, 0));
			image.close();
		}
	}
	
	public void bindCursor(AssetLocation id, Window window) {
		long cursor = cursors.getOrDefault(id, 0L);
		if(cursor != currentCursor) {
			currentCursor = cursor;
			GLFW.glfwSetCursor(window.getId(), cursor);
		}
		if(cursor != 0) ignore = true;
	}
	
	public void clearCursor(Window window) {
		if(ignore) {
			ignore = false;
			return;
		}
		if(currentCursor != 0) {
			currentCursor = 0;
			GLFW.glfwSetCursor(window.getId(), 0);
		}
	}
	
	@Override
	public void reload() {
		cursors.values().retainAll(LongCollections.empty(), GLFW::glfwDestroyCursor);
		loadCursors();
	}
	
	@Override
	public void destroy() {
		cursors.values().retainAll(LongCollections.empty(), GLFW::glfwDestroyCursor);
	}
	
	private void loadCursors() {
		for(int i = 0,m = LOCATIONS.length;i < m;i++) { 
			cursors.put(LOCATIONS[i], GLFW.glfwCreateStandardCursor(GLFW.GLFW_ARROW_CURSOR + i));
		}
		for(Entry<AssetLocation, AssetLocation> entry : Object2ObjectMaps.fastIterable(customCursors)) {
			GLFWImage image = TextureManager.create(entry.getValue());
			if(image != null) {
				cursors.put(entry.getKey(), GLFW.glfwCreateCursor(image, 0, 0));
				image.close();
			}
		}
	}
}
