package sim.util;

import java.awt.*;
import java.awt.event.*;

public class LightTextField extends Container implements MouseMotionListener, MouseListener, FocusListener, KeyListener
{
	private LightTextFieldParent parent;
	private Font currentFont;
	private int columns;
	private char defaultCharacter;

	public LightTextField(LightTextFieldParent listener, int initialColumns, Font initialFont, char initialFill)
	{
		super();

		this.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
		this.parent = listener;
		this.currentFont = initialFont;
		this.columns = initialColumns;
		this.defaultCharacter = initialFill;

		FontMetrics fm = this.getFontMetrics(this.currentFont);

		this.setSize(fm.charWidth('W') * this.columns, fm.getHeight());

		for(int index = 0; index < this.columns; index++)
			this.add(new LightCharacter(this.defaultCharacter, this.currentFont, index));

		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addFocusListener(this);
		this.addKeyListener(this);

		this.setCursor(new Cursor(Cursor.TEXT_CURSOR));
	}

	public String getText()
	{
		char result[] = new char[this.columns];

		for(int index = 0; index < this.columns; index++)
			result[index] = ((LightCharacter)this.getComponent(index)).getCharacter();

		return (new String(result));
	}

	public void setText(String text)
	{
		for(int index = 0; index < this.columns; index++)
			((LightCharacter)this.getComponent(index)).setCharacter(text.charAt(index));
	}

	public void setColumns(int c)
	{
		this.removeAll();

		this.columns = c;

		FontMetrics fm = this.getFontMetrics(this.currentFont);
		this.setSize(fm.charWidth('W') * this.columns, fm.getHeight());

		for(int index = 0; index < this.columns; index ++)
			this.add(new LightCharacter(this.defaultCharacter, this.currentFont, index));
	}

	public int getColumns()
	{
		return this.columns;
	}

	public void setFont(Font f)
	{
		this.currentFont = f;

		FontMetrics fm = this.getFontMetrics(this.currentFont);
		this.setSize(fm.charWidth('W') * this.columns, fm.getHeight());

		for(int index = 0; index < this.columns; index++)
			((LightCharacter)this.getComponent(index)).setFont(f);
	}

/* ==================================================================
	Mouse handling
	================================================================= */
	private LightCharacter selected = null;
	private boolean mouseDown = false;

	public void mouseDragged(MouseEvent e)
	{
		int position, index;

		if(this.mouseDown && this.contains(e.getPoint()))
		{
			LightCharacter source = (LightCharacter)this.getComponentAt(e.getPoint());

			if(this.selected != source)
			{
				this.selected.deSelect();
				source.select();
				this.selected = source;
				this.parent.respondToChanges();
			}
		}
	}

	public void mouseMoved(MouseEvent e)
	{
	}

	public void mouseClicked(MouseEvent e)
	{
	}

	public void mouseEntered(MouseEvent e)
	{
	}

	public void mouseExited(MouseEvent e)
	{

	}

	public void mousePressed(MouseEvent e)
	{
		if(this.selected != null)
			this.selected.deSelect();

		LightCharacter source = (LightCharacter)this.getComponentAt(e.getPoint());
		source.select();
		this.selected = source;
		this.parent.respondToChanges();
		this.requestFocus();

		this.mouseDown = true;
	}

	public void mouseReleased(MouseEvent e)
	{
		this.mouseDown = false;
	}

/* ==================================================================
	Focus handling
	================================================================= */
	public void focusGained(FocusEvent e)
	{
	}

	public void focusLost(FocusEvent e)
	{
		if(selected != null)
		{
			this.selected.deSelect();
			this.selected = null;

			this.parent.respondToString(this.getText());
		}
	}

/* ==================================================================
	Key handling
	================================================================= */
	public void keyPressed(KeyEvent e)
	{

	}

	public void keyReleased(KeyEvent e)
	{
		LightCharacter affected;
		char input;

		if((!this.mouseDown) && (this.selected != null))
		{
			switch(e.getKeyCode())
			{
				case KeyEvent.VK_ESCAPE:
					this.selected.deSelect();
					this.selected = null;
					this.parent.escape();
					break;
				case KeyEvent.VK_HOME:
					this.selected.deSelect();
					this.selected = (LightCharacter)this.getComponent(this.columns - 1);
					this.selected.select();
					this.parent.respondToChanges();
					break;
				case KeyEvent.VK_END:
					this.selected.deSelect();
					this.selected = (LightCharacter)this.getComponent(0);
					this.selected.select();
					this.parent.respondToChanges();
					break;
				case KeyEvent.VK_ENTER:
					this.selected.deSelect();
					this.selected = null;
					parent.respondToString(this.getText());
					break;
				case KeyEvent.VK_LEFT:
					if(this.selected.getPosition() != 0)
					{
						this.selected.deSelect();
						this.selected = (LightCharacter)this.getComponent(this.selected.getPosition() - 1);
						this.selected.select();
						this.parent.respondToChanges();
					}
					break;
				case KeyEvent.VK_RIGHT:
					if(this.selected.getPosition() != (this.columns - 1))
					{
						this.selected.deSelect();
						this.selected = (LightCharacter)this.getComponent(this.selected.getPosition() + 1);
						this.selected.select();
						this.parent.respondToChanges();
					}
					break;

				default:
					input = e.getKeyChar();

					if(input != KeyEvent.CHAR_UNDEFINED)
					{
						this.selected.setCharacter(input);
					/*	this.selected.deSelect();

						if(this.selected.getPosition() != (this.columns - 1))
						{
							this.selected = (LightCharacter)this.getComponent(this.selected.getPosition() + 1);
							this.selected.select();
							this.parent.respondToChanges();
						}
						else
						{
							this.selected = null;
							this.parent.respondToString(this.getText());
						}*/

						if(this.selected.getPosition() != (this.columns - 1))
						{
							this.selected.deSelect();
							this.selected = (LightCharacter)this.getComponent(this.selected.getPosition() + 1);
							this.selected.select();
						}

						this.parent.respondToChanges();
					}
			}
		}
	}

	public void keyTyped(KeyEvent e)
	{
	}

/* ==================================================================
	Class to handle characters
	================================================================= */

	public class LightCharacter extends Component
	{
		private char value;
		private Font currentFont;
		private boolean selected = false;
		private int position;

		public LightCharacter(char c, Font f, int location)
		{
			this.value = c;
			this.position = location;
			this.setFont(f);

			FontMetrics fm = this.getFontMetrics(this.currentFont);
			this.setSize(fm.charWidth('W'), fm.getHeight());
		}

		public Dimension getPreferredSize()
		{
			return this.getSize();
		}

		public void setCharacter(char c)
		{
			this.value = c;
		}

		public char getCharacter()
		{
			return this.value;
		}

		public void setFont(Font f)
		{
			this.currentFont = f;

			FontMetrics fm = this.getFontMetrics(this.currentFont);

			this.setSize(fm.charWidth('W'), fm.getHeight());
		}

		public void paint(Graphics g)
		{
			Dimension size = this.getSize();
			FontMetrics fm = this.getFontMetrics(this.currentFont);
			int offsetX = (size.width - fm.charWidth(this.value)) / 2;
			int offsetY = fm.getAscent();
			String toDraw = (new Character(this.value)).toString();

			if(this.selected)
			{
				g.setColor(Color.blue.darker());
				g.fillRect(0, 0, size.width, size.height);
				g.setColor(Color.white);
			}
			else
			{
				g.setColor(Color.white);
				g.fillRect(0, 0, size.width, size.height);
				g.setColor(Color.black);
			}

			g.setFont(this.currentFont);
			g.drawString(toDraw, offsetX, offsetY);
		}

		public void select()
		{
			this.selected = true;
		}

		public void deSelect()
		{
			this.selected = false;
		}

		public int getPosition()
		{
			return this.position;
		}
	}
}
