package projectzombie.menu.gui;

import java.util.ArrayList;

import org.lwjgl.glfw.GLFW;

import gl_engine.matrix.Matrix4;
import gl_engine.vec.Vec2d;
import projectzombie.input.CursorPosCallback;
import projectzombie.input.types.InputGUITextBox;

public class GUI implements GUIContainer
{
	private ArrayList<GUIComponent> components = new ArrayList<GUIComponent>();
	
	public GUISelectable selected;
	private InputGUITextBox text_box;
	
	private static boolean move_last = false;
	
	public void setTextBox(InputGUITextBox text_box) {
		this.text_box = text_box;
	}
	
	public void setSelected(GUISelectable selected) {
		if(this.selected != null) {
			this.selected.setSelected(false);
		}
		this.selected = selected;
		if(this.selected != null) {
			this.selected.setSelected(true);
		}
	}
	
	@Override
	public void render(Matrix4 matrix, Vec2d mousePos, boolean canHover) {
		for(GUIComponent c : components) {
			c.render(matrix, mousePos, canHover);
		}
	}
	
	public Vec2d getCursorPos() {
		return CursorPosCallback.getCursorPos();
	}
	
	public void render() {
		this.render(Matrix4.identity(), getCursorPos(), true);
	}

	@Override
	public void add(GUIComponent c) {
		components.add(c);
	}
	
	public void onMove(boolean status, double angle)
	{
		if(this.selected == null) {
			return;
		}
		
		if(status) {
			if(!move_last) {
				move_last = true;
				
				this.selected.setSelected(false);
				GUISelectable selected = null;
				
				// Up / North
				if(angle > 315 || angle <= 45) {
					selected = this.selected.getNeighbour(GUISelectableDirection.UP);
				}
				
				// Right / East
				if(angle > 45 && angle <= 135) {
					selected = this.selected.getNeighbour(GUISelectableDirection.RIGHT);
				}
				
				// Down / South
				if(angle > 135 && angle <= 225) {
					selected = this.selected.getNeighbour(GUISelectableDirection.DOWN);
				}
				
				// Left / West
				if(angle > 225 && angle <= 315) {
					selected = this.selected.getNeighbour(GUISelectableDirection.LEFT);
				}
				
				if(selected != null) {
					this.selected = selected;
				}
				
				this.selected.setSelected(true);
			}
		}
		
		else if(move_last) {
			move_last = false;
		}
	}

	@Override
	public boolean checkMouseHover(Vec2d pos) {
		return true;
	}

	@Override
	public void onMouseClick(Vec2d pos)
	{
		if(text_box != null && text_box instanceof GUIComponent && !((GUIComponent)text_box).checkMouseHover(pos)) {
			text_box.setFocus(false);
			text_box = null;
		}
		
		Vec2d cursorPos = getCursorPos();
		
		for(GUIComponent c : components) {
			if(c.checkMouseHover(cursorPos)) {
				c.onMouseClick(cursorPos);
			}
		}
	}
	
	@Override
	public void onRightClick(Vec2d pos)
	{
		Vec2d cursorPos = getCursorPos();
		
		for(GUIComponent c : components) {
			if(c.checkMouseHover(cursorPos)) {
				c.onRightClick(cursorPos);
			}
		}
	}
	
	public void onMouseClick() {
		this.onMouseClick(getCursorPos());
	}
	
	public void onRightClick() {
		this.onRightClick(getCursorPos());
	}
	
	@Override
	public void onBack()
	{
		if(text_box == null)
		{
			for(GUIComponent c : components) {
				c.onBack();
			}
		}
		
		else
		{
			text_box.setFocus(false);
			text_box = null;
		}
	}
	
	@Override
	public void onActivate() {
		for(GUIComponent c : components) {
			c.onActivate();
		}
	}

	@Override
	public void update(Vec2d mousePos) {
		for(GUIComponent c : components) {
			c.update(mousePos);
		}
	}
	
	@Override
	public void onScroll(Vec2d mousePos, double amount) {
		for(GUIComponent c : components) {
			c.onScroll(mousePos, amount);
		}
	}
	
	public void onScroll(int amount) {
		onScroll(getCursorPos(), amount);
	}
	
	@Override
	public void clear() {
		components.clear();
	}

	public void type(char character) {
		if(text_box != null) {
			text_box.onPressed(character);
		}
	}

	public void pasteKey() {
		if(text_box != null) {
			text_box.onDelete();
		}
	}
	
	public void keyPress(int key) {
		if(text_box != null)
		{
			switch(key)
			{
			case GLFW.GLFW_KEY_LEFT:
				text_box.onMoveCursor(-1);
				break;
			case GLFW.GLFW_KEY_RIGHT:
				text_box.onMoveCursor(1);
				break;
			case GLFW.GLFW_KEY_DELETE:
				text_box.onDelete();
				break;
			case GLFW.GLFW_KEY_BACKSPACE:
				text_box.onBackspace();
				break;
			case GLFW.GLFW_KEY_HOME:
				text_box.onHome();
				break;
			case GLFW.GLFW_KEY_END:
				text_box.onEnd();
				break;
			}
		}
	}

	public void keyPressCtrl(int key) {
		if(text_box != null)
		{
			switch(key)
			{
			case GLFW.GLFW_KEY_V:
				text_box.onPaste();
				break;
			}
		}
	}
	
	@Override
	public GUIItemSlot getHoveringItemSlot(Vec2d mousePos)
	{
		for(GUIComponent c : components)
		{
			if(c.checkMouseHover(mousePos))
			{
				if(c instanceof GUIItemSlot) {
					return (GUIItemSlot)c;
				}
				
				if(c instanceof GUIContainer)
				{
					GUIItemSlot slot = ((GUIContainer)c).getHoveringItemSlot(mousePos);
					
					if(slot != null) {
						return slot;
					}
				}
			}
		}
		
		return null;
	}
}
