package speiger.src.coreengine.rendering.gui.components.base;

import java.util.List;

import speiger.src.collections.ints.sets.IntSet;

public interface IInteractableContainer extends IInteractable
{
	public List<? extends IInteractable> getChildren();
	
	public void setFocusedChild(IInteractable child);
	public IInteractable getFocusedChild();
	public IntSet getActiveButtons();
	
	public default IInteractable getChildAt(int mouseX, int mouseY) {
		List<? extends IInteractable> children = getChildren();
		for(int i = 0,m=children.size();i<m;i++) {
			IInteractable interact = children.get(i);
			if(interact.isMouseColliding(mouseX, mouseY) && IRecursiveInteractionContainer.validateContainer(interact, mouseX, mouseY)) return interact;
		}
		return null;
	}
	
	@Override
	default boolean onMouseClick(int button, int mouseX, int mouseY) {
		IntSet active = getActiveButtons();
		if(active.size() > 0 && getFocusedChild() != null) {
			IInteractable focus = getFocusedChild();
			if(focus.isMouseColliding(mouseX, mouseY) && focus.onMouseClick(button, mouseX, mouseY)) {
				active.add(button);
				return true;
			}
			return false;
		}
		List<? extends IInteractable> children = getChildren();
		for(int i = 0,m=children.size();i<m;i++) {
			IInteractable interact = children.get(i);
			if(interact.isMouseColliding(mouseX, mouseY) && interact.onMouseClick(button, mouseX, mouseY)) {
				setFocusedChild(interact);
				active.add(button);
				return true;
			}
		}
		if(active.isEmpty() && getFocusedChild() != null) setFocusedChild(null);
		return false;
	}
	
	@Override
	default boolean onMouseDragged(int mouseX, int mouseY, int diffX, int diffY) {
		return getFocusedChild() != null && getActiveButtons().contains(0) && getFocusedChild().onMouseDragged(mouseX, mouseY, diffX, diffY);
	}
	
	@Override
	default boolean onMouseReleased(int button, int mouseX, int mouseY) {
		getActiveButtons().remove(button);
		IInteractable interact = getChildAt(mouseX, mouseY);
		return interact != null && interact == getFocusedChild() && interact.onMouseReleased(button, mouseX, mouseY);
	}
	
	@Override
	default boolean onMouseScroll(int scroll, int mouseX, int mouseY) {
		IInteractable interact = getChildAt(mouseX, mouseY);
		return interact != null && interact.onMouseScroll(scroll, mouseX, mouseY);
	}
	
	@Override
	default boolean onKeyPressed(int key, int mouseX, int mouseY) {
		IInteractable interact = getFocusedChild();
		if(interact != null && (interact.onKeyPressed(key, mouseX, mouseY) || interact.isPriorityKeyTarget())) return true;
		List<? extends IInteractable> children = getChildren();
		for(int i = 0,m=children.size();i<m;i++) {
			if(children.get(i).onKeyPressed(key, mouseX, mouseY)) return true;
		}
		return false;
	}
	
	@Override
	default boolean onKeyReleased(int key, int mouseX, int mouseY) {
		IInteractable interact = getFocusedChild();
		if(interact != null && (interact.onKeyReleased(key, mouseX, mouseY) || interact.isPriorityKeyTarget())) return true;
		List<? extends IInteractable> children = getChildren();
		for(int i = 0,m=children.size();i<m;i++) {
			if(children.get(i).onKeyReleased(key, mouseX, mouseY)) return true;
		}
		return false;
	}
	
	@Override
	default boolean onKeyTyped(char letter, int codepoint) {
		return getFocusedChild() != null && getFocusedChild().onKeyTyped(letter, codepoint);
	}
	
	public static interface IRecursiveInteractionContainer extends IInteractableContainer {
		private static boolean validateContainer(IInteractable interact, int mouseX, int mouseY) {
			return !(interact instanceof IRecursiveInteractionContainer container) || container.getChildAt(mouseX, mouseY) != null;
		}
		
		@Override
		default boolean isMouseColliding(int mouseX, int mouseY) {
			return true;
		}
	}
}
