package speiger.src.coreengine.rendering.inputOld;

import java.util.function.BiPredicate;

import org.lwjgl.glfw.GLFW;

import speiger.src.coreengine.rendering.inputOld.bindings.InputBinding;
import speiger.src.coreengine.rendering.inputOld.bindings.utils.BindingType;
import speiger.src.coreengine.rendering.inputOld.events.KeyEvent.CharTypeEvent;
import speiger.src.coreengine.rendering.inputOld.events.KeyEvent.KeyPressEvent;
import speiger.src.coreengine.rendering.inputOld.window.Window;
import speiger.src.coreengine.utils.eventbus.EventBus;

public class Keyboard
{
	public static final Keyboard INSTANCE = new Keyboard();
	boolean[] pressedKeys = new boolean[350];
	boolean[] nonConsumedKeys = new boolean[350];
	EventBus bus;
	BiPredicate<Integer, Keyboard> filter;
	
	public void init(EventBus bus, Window window) {
		this.bus = bus;	
		window.addCallback(T -> GLFW.glfwSetKeyCallback(T, this::onKeyTyped));
		window.addCallback(T -> GLFW.glfwSetCharCallback(T, this::onCharTyped));
	}
	
	public static void setFilter(BiPredicate<Integer, Keyboard> filter) {
		INSTANCE.filter = filter;
	}
	
	public static void clearFilter() {
		setFilter(null);
	}
	
	protected void onKeyTyped(long window, int key, int scancode, int action, int mods) {
		if(key > 350 || key < 0) return;
		if(action >= 1) {
			pressedKeys[key] = true;
			onKeyPressed(key);
		}
		else {
			pressedKeys[key] = false;
			nonConsumedKeys[key] = false;
			InputBinding.BINDINGS.updatePressing(BindingType.KEYBOARD, key, false);
		}
	}
	
	public void onKeyPressed(int key) {
		if(filter == null || filter.test(key, this)) {
			KeyPressEvent event = new KeyPressEvent(key);
			bus.post(event);
			if(event.isCanceled()) return;
			nonConsumedKeys[key] = true;
			InputBinding.BINDINGS.updatePressing(BindingType.KEYBOARD, key, true);
		}
	}
	
	public void onCharTyped(long windowId, int codepoint) {
		bus.post(new CharTypeEvent((char)codepoint, codepoint));
	}
	
	public static boolean isCtrlDown() {
		return isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL) || isKeyPressed(GLFW.GLFW_KEY_RIGHT_CONTROL);
	}

	public static boolean isShiftDown() {
		return isKeyPressed(GLFW.GLFW_KEY_LEFT_SHIFT) || isKeyPressed(GLFW.GLFW_KEY_RIGHT_SHIFT);
	}

	public static boolean isAltDown() {
		return isKeyPressed(GLFW.GLFW_KEY_LEFT_ALT) || isKeyPressed(GLFW.GLFW_KEY_RIGHT_ALT);
	}
	
	public static boolean isPrintableKey(int key) {
		return key <= 162;
	}
	
	public static boolean isKeyFullyPressed(int key) {
		return INSTANCE.isPressed(key) && !INSTANCE.isConsumed(key);
	}
	
	public static boolean isKeyPressed(int key) {
		return INSTANCE.isPressed(key);
	}
	
	public boolean isPressed(int key) {
		return pressedKeys[key];
	}
	
	public boolean isConsumed(int key) {
		return !nonConsumedKeys[key];
	}
}
