package com.one;

import java.util.Vector;

public class AsyncRenderer extends Renderer implements Runnable
{
	public static final int KEY_PRESSED = 0;
	public static final int KEY_RELEASED = 1;
	public static final int KEY_REPEATED = 2;

	public static class KeyEvent
	{
		public int type;
		public int key;

		public KeyEvent(int type, int key)
		{
			this.type = type;
			this.key = key;
		}
	}

	protected final Vector queue = new Vector();
	protected boolean isrunning;
	protected KeyEvent currevent;

	public AsyncRenderer()
	{
		(new Thread(this, "AsyncRenderer/EventDispatch")).start();
	}

	public void keyPressed(int keyCode)
	{
		enqueueEvent(new KeyEvent(KEY_PRESSED, keyCode));
	}

	public void keyReleased(int keyCode)
	{
		enqueueEvent(new KeyEvent(KEY_RELEASED, keyCode));
	}

	public void keyRepeated(int keyCode)
	{
		enqueueEvent(new KeyEvent(KEY_REPEATED, keyCode));
	}

	public void enqueueEvent(KeyEvent event)
	{
		synchronized(queue)
		{
			if(isrunning)
			{
				if(event.type != KEY_REPEATED && (event.type == currevent.type ? event.key != currevent.key : true))
				{
					if(queue.isEmpty())
					{
						queue.addElement(event);
					}
					else
					{
						KeyEvent lastevent = (KeyEvent)queue.elementAt(queue.size() - 1);

						if(event.type != lastevent.type || event.key != lastevent.key)
						{
							queue.addElement(event);
						}
					}
				}
			}
			else
			{
				queue.addElement(event);
				queue.notifyAll();
			}
		}
	}

	public void run()
	{
		while(true)
		{
			try
			{
				synchronized(queue)
				{
					if(queue.isEmpty())
					{
						isrunning = false;
						queue.wait();
					}

					isrunning = true;

					currevent = (KeyEvent)queue.elementAt(0);
					queue.removeElementAt(0);
				}

				if(currevent.type == KEY_PRESSED)
				{
					super.keyPressed(currevent.key);
				}
				else if(currevent.type == KEY_RELEASED)
				{
					super.keyReleased(currevent.key);
				}
				else
				{
					super.keyRepeated(currevent.key);
				}
			}
			catch(InterruptedException ie)
			{
				System.out.println("Event dispatch thread interrupted");
			}
		}
	}
}