package eng;

import java.awt.Cursor;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;

import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;

import com.sun.opengl.util.Animator;

@SuppressWarnings("serial")
public class GameState extends GLCanvas implements KeyListener {
	
	protected boolean ended;
	protected boolean paused;
	
	protected boolean initiated;
	
	protected String nextGameState;
	
	protected String audio;
	protected String newAudio;
	
	protected Data data;
	
	protected Input input;
	
	private ArrayList<Integer> keysDown;
	
	private boolean[] mouseButtons;
	private double mouseScroll;
	
	protected Animator animator;
	
	public GameState() {
		super(new GLCapabilities());
	}
	
	public void initiate(Data data) {
		
		this.data = data;
		
		input = new Input();
		
		audio = "";
		
		keysDown = new ArrayList<Integer>();
		
		mouseButtons = new boolean[3];
		mouseScroll = 0;
		
		for(int i = 0; i < 3; i++)
			mouseButtons[i] = false;
		
		addFocusListener(new FocusListener() {
			
			public void focusGained(FocusEvent e) {
				keysDown = new ArrayList<Integer>();
				
			}
			
			public void focusLost(FocusEvent e) {
				keysDown = new ArrayList<Integer>();
			}
		});
		
		addKeyListener(this);
		
		addMouseListener(new MouseAdapter() {
			
			public void mousePressed(MouseEvent e) {
				
				if(e.getButton() == MouseEvent.BUTTON1)
					mouseButtons[0] = true;
				
				if(e.getButton() == MouseEvent.BUTTON2)
					mouseButtons[1] = true;
				
				if(e.getButton() == MouseEvent.BUTTON3)
					mouseButtons[2] = true;
			}
			
			public void mouseReleased(MouseEvent e) {
				
				if(e.getButton() == MouseEvent.BUTTON1)
					mouseButtons[0] = false;
				
				if(e.getButton() == MouseEvent.BUTTON2)
					mouseButtons[1] = false;
				
				if(e.getButton() == MouseEvent.BUTTON3)
					mouseButtons[2] = false;
			}
		});
		
		addMouseWheelListener(new MouseWheelListener() {

			public void mouseWheelMoved(MouseWheelEvent e) {
				mouseScroll = e.getPreciseWheelRotation();
			}
		});
		
		setFocusable(true);
		
		addGLEventListener(new GraphicListener());
		
		animator = new Animator(this);
		animator.start();
		
		initiated = true;
	}
	
	public void resume(Data data) {
		
		this.data = data;
		
		paused = false;
		nextGameState = null;
		
		repaint();
		invalidate();
		validate();
	}
	
	public void updateInput() {
		
		input.setKeysDown(keysDown);
		
		input.setMouseButtons(mouseButtons);
		input.setMouseScroll(mouseScroll);
		
		PointerInfo pointer = MouseInfo.getPointerInfo();
		Point point = pointer.getLocation();
		
		input.setMousePositionX(point.getX());
		input.setMousePositionY(point.getY());
	}
	
	public void update() {
		
	}
	
	public Data getData() {
		return data;
	}
	
	public boolean isInitiated() {
		return initiated;
	}
	
	public boolean isPaused() {
		return paused;
	}
	
	public boolean hasEnded() {
		return ended;
	}
	
	public String getNextGameState() {
		return nextGameState;
	}
	
	public String getAudio() {
		return audio;
	}
	
	public String getNewAudio() {
		
		String ret = newAudio;
		newAudio = null;
		
		return ret;
	}
	
	public Cursor getCursor() {
		return null;
	}
	
	public void setKeysDown(ArrayList<Integer> keysDown) {
		this.keysDown = keysDown;
	}
	
	public ArrayList<Integer> getKeysDown() {
		return keysDown;
	}

	public void keyPressed(KeyEvent ke) {
		
		boolean add = true;
		ArrayList<Integer> newDown = new ArrayList<Integer>(0);
		
		for (int i = 0; i < keysDown.size(); i++) {
			
			if (keysDown.get(i) == ke.getKeyCode()) {
				add = false;
				break;
			}
			
			newDown.add(keysDown.get(i));
		}
		
		if (add) {
			newDown.add(ke.getKeyCode());
			keysDown = newDown;
		}
	}
	
	public void keyReleased(KeyEvent ke) {
		
		ArrayList<Integer> newDown = new ArrayList<Integer>(0);
		
		for (int i = 0; i < keysDown.size(); i++)
			if (keysDown.get(i) != ke.getKeyCode())
				newDown.add(keysDown.get(i));
		
		keysDown = newDown;
	}
	
	public void keyTyped(KeyEvent ke) {
		
	}
	
	public void GLDisplay(GLAutoDrawable glad) {
		
	}
	
	public void GLDisplayChanged(GLAutoDrawable glad,
			boolean modeChanged, boolean deviceChanged) {
		
	}
	
	public void GLInit(GLAutoDrawable glad) {
		
	}
	
	public void GLReshape(GLAutoDrawable glad,
			int x, int y, int width, int height) {
		
	}
	
	public class GraphicListener implements GLEventListener {
		
		public void display(GLAutoDrawable glad) {
			GLDisplay(glad);
		}
		
		public void displayChanged(GLAutoDrawable glad, boolean arg1, boolean arg2) {
			GLDisplayChanged(glad, arg1, arg2);
		}
		
		public void init(GLAutoDrawable glad) {
			GLInit(glad);
		}
		
		public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
			GLReshape(glad, x, y, width, height);
		}
	}
}