package graphics.userInterface;

import java.awt.event.KeyEvent;
import java.io.Serializable;

import br.ufsc.inf.leobr.cliente.Jogada;

public class Menu implements Serializable, Jogada {
	private static final long serialVersionUID = -1181246299988473592L;
	
	private Window[] options;
	private Window cursor;
	
	private int currentOption = 0;
	private int x;
	private int y;
	private int standardPosition;
	private int highlitPosition;
	private int cursorPosition;
	
	private boolean confirmed;
	private boolean hidden;
	private boolean disabled;
	
	private Runnable cancelMethod;
	
	public Menu(int x, int y, String[] optionName) {
		this.x = x - 30;
		this.y = y;
		
		standardPosition = x;
		highlitPosition = x + 20;
		cursorPosition = x - 10;

		cursor = new Window(cursorPosition, y, 30, 30, ">>");
		options = new Window[optionName.length];
		
		for (int i = 0; i < optionName.length; i++) {
			if (i == 0) {
				options[i] = new Window(highlitPosition, y + 30 * i, 180, 30, optionName[i]);
			} else {
				options[i] = new Window(standardPosition, y + 30 * i, 180, 30, optionName[i]);
			}
		}
	}
	
	public Menu(int x, int y, String[] optionName, Runnable[] methods) {
		this.x = x - 30;
		this.y = y;
		
		standardPosition = x;
		highlitPosition = x + 20;
		cursorPosition = x - 10;

		cursor = new Window(cursorPosition, y, 30, 30, ">>");
		options = new Window[optionName.length];
		
		for (int i = 0; i < optionName.length; i++) {
			if (i == 0) {
				options[i] = new Window(highlitPosition, y + 30 * i, 180, 30, optionName[i]);
			} else {
				options[i] = new Window(standardPosition, y + 30 * i, 180, 30, optionName[i]);
			}
			
			options[i].setExecuteMethod(methods[i]);
		}
	}
	
	public void inputManager(KeyEvent e) throws InterruptedException {
		if (disabled == false) {
			if (hidden == false) {
				// Direcionais
				if (e.getKeyCode() == KeyEvent.VK_S && !confirmed) {
					if (currentOption < options.length - 1) {
						undoHighlightOption(options[currentOption]);
						currentOption++;
						highlightOption(options[currentOption]);
						cursor.setLocation(x + 20, options[currentOption].getY());
					}
				}
				if (e.getKeyCode() == KeyEvent.VK_W && !confirmed) {
					if (currentOption > 0) {
						undoHighlightOption(options[currentOption]);
						currentOption--;
						highlightOption(options[currentOption]);
						cursor.setLocation(x + 20, options[currentOption].getY());
					}
				}			
			}
			
			// Confirma
			if (e.getKeyCode() == KeyEvent.VK_K && !confirmed) {
				// Executa opção
				options[currentOption].executeMethod();
				confirmed = true;
			}
			
			// Cancela
			if (e.getKeyCode() == KeyEvent.VK_L && confirmed) {
				// Executa o método de cancelamento do menu
				cancelMethod.run();
				confirmed = false;
			}
		}
	}
	
	public void highlightOption(Window option) {
		option.setLocation(option.getX() + 20, option.getY());
	}
	
	public void undoHighlightOption(Window option) {
		option.setLocation(option.getX() - 20, option.getY());
	}
	
	public void hide() {
		hidden = true;
		cursor.hide();
		
		for (int i = 0; i < options.length; i++) {
			options[i].hide();
		}
	}
	
	public void show() {
		hidden = false;
		cursor.show();
		
		for (int i = 0; i < options.length; i++) {
			options[i].show();
		}
	}
	
	public void reset() {
		currentOption = 0;
		confirmed = false;
		
		resetTheFuckinPositions();
	}
	
	private void resetTheFuckinPositions() {
		for (int i = 0; i < options.length; i++) {
			if (i == 0) {
				options[i].setLocation(highlitPosition, options[i].getY());
			} else {
				options[i].setLocation(standardPosition, options[i].getY());
			}
		}
		
		cursor.setLocation(cursorPosition, options[currentOption].getY());
	}

	public int getCurrentOption() {
		return currentOption;
	}

	public void setCurrentOption(int currentOption) {
		this.currentOption = currentOption;
	}

	public Window[] getOptions() {
		return options;
	}

	public Window getCursor() {
		return cursor;
	}
	
	public boolean isConfirmed() {
		return confirmed;
	}
	
	public void resetConfirmation() {
		confirmed = false;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public boolean isHidden() {
		return hidden;
	}

	public boolean isDisabled() {
		return disabled;
	}
	
	public void enable() {
		disabled = false;
	}
	
	public void disable() {
		disabled = true;
	}

	public Runnable getCancelMethod() {
		return cancelMethod;
	}

	public void setCancelMethod(Runnable cancelMethod) {
		this.cancelMethod = cancelMethod;
	}
}
