package com.vmx;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

public class keyConfig
{
	public static final int ID_USER = 256;

	public static final String HOT_KEY_SUFFIX = "!";
	public static final String HELD_KEY_SUFFIX = "+";

	public static class KeyInfo
	{
		private int id;
		private int code;
		private String name;
		private String abbr;

		public KeyInfo(int id, int code, String name, String abbr)
		{
			this.id = id;
			this.code = code;
			this.name = name;
			this.abbr = abbr;
		}

		public KeyInfo(DataInputStream dis) throws IOException
		{
			id = dis.readInt();
			code = dis.readInt();
			name = dis.readUTF();
			abbr = dis.readUTF();
		}

		public void write(DataOutputStream dos) throws IOException
		{
			dos.writeInt(id);
			dos.writeInt(code);
			dos.writeUTF(name);
			dos.writeUTF(abbr);
		}

		public void setCode(int code)
		{
			this.code = code;
		}

		public void setName(String name)
		{
			this.name = name;
		}

		public void setAbbreviation(String abbr)
		{
			this.abbr = abbr;
		}
		
		public int getCode()
		{
			return code;
		}

		public String getName()
		{
			return name;
		}

		public String getAbbreviation()
		{
			return abbr;
		}

		public int hashCode()
		{
			return id;
		}

		public boolean equals(Object obj)
		{
			if(obj == null)
			{
				return false;
			}

			if(getClass() != obj.getClass())
			{
				return false;
			}

			final KeyInfo other = (KeyInfo)obj;

			if(this.id != other.id)
			{
				return false;
			}
			
			return true;
		}
	}

	protected static Hashtable keys = new Hashtable();
	protected static Hashtable actions = new Hashtable();

	public static int getNextID(boolean system)
	{
		Enumeration e = keys.elements();

		int maxid = -1;
		int id;

		if(system)
		{
			while(e.hasMoreElements())
			{
				id = ((KeyInfo)e.nextElement()).hashCode();

				if(id < ID_USER && id > maxid)
				{
					maxid = id;
				}
			}

			return maxid + 1;
		}
		else
		{
			while(e.hasMoreElements())
			{
				id = ((KeyInfo)e.nextElement()).hashCode();

				if(id >= ID_USER && id > maxid)
				{
					maxid = id;
				}
			}

			if(maxid >= 0)
			{
				return maxid + 1;
			}
			else
			{
				return ID_USER;
			}
		}
	}

	public static KeyInfo addKey(int keyCode, String name, String abbreviation, int action, boolean system)
	{
		KeyInfo key = new KeyInfo(getNextID(system), keyCode, name, abbreviation);

		keys.put(new Integer(keyCode), key);
		actions.put(key, new Integer(action));

		return key;
	}

	public static void deleteKey(KeyInfo key)
	{
		keys.remove(new Integer(key.getCode()));
		actions.remove(key);
	}
	
	public static void setAction(KeyInfo key, int action)
	{
		actions.put(key, new Integer(action));
	}

	public static int getAction(int keyCode)
	{
		KeyInfo key = (KeyInfo)keys.get(new Integer(keyCode));

		if(key == null)
		{
			return -1;
		}

		return getAction(key);
	}

	public static int getAction(KeyInfo key)
	{
		Integer action = (Integer)actions.get(key);

		if(action != null)
		{
			return action.intValue();
		}

		return -1;
	}

	public static Enumeration listKeys()
	{
		Vector vector = new Vector(actions.size());

		Enumeration e = actions.keys();
		KeyInfo key;
		boolean added;

		while(e.hasMoreElements())
		{
			key = (KeyInfo)e.nextElement();
			added = false;

			for(int i = 0; i < vector.size(); i++)
			{
				if(key.hashCode() < ((KeyInfo)vector.elementAt(i)).hashCode())
				{
					vector.insertElementAt(key, i);
					added = true;
					break;
				}
			}

			if(!added)
			{
				vector.addElement(key);
			}
		}

		return vector.elements();
	}

	public static void writeConfig(DataOutputStream dos) throws IOException
	{
		dos.writeInt(actions.size());

		Enumeration e = actions.keys();
		KeyInfo key;

		while(e.hasMoreElements())
		{
			key = (KeyInfo)e.nextElement();

			key.write(dos);
			dos.writeInt(((Integer)actions.get(key)).intValue());
		}
	}

	public static void readConfig(DataInputStream dis) throws IOException
	{
		int count = dis.readInt();

		KeyInfo key;

		for(int i = 0; i < count; i++)
		{
			key = new KeyInfo(dis);

			keys.put(new Integer(key.getCode()), key);
			actions.put(key, new Integer(dis.readInt()));
		}
	}

	public static void addDefaultKeys()
	{
		actions.clear();
		keys.clear();
		
		addKey(gkcCanvas.KEY_LSK, keyName(Locale.KEY_LSK), "LS", Locale.OPTIONS_CMD, true);
		addKey(gkcCanvas.KEY_RSK, keyName(Locale.KEY_RSK), "RS", Locale.BACK_CMD, true);
		addKey(gkcCanvas.KEY_DIAL, keyName(Locale.KEY_DIAL), "S", Locale.MARK_CMD, true);
		addKey(gkcCanvas.KEY_CANCEL, keyName(Locale.KEY_CANCEL), "E", Locale.BACK_CMD, true);
		addKey(gkcCanvas.KEY_UP, keyName(Locale.KEY_UP), "U", Locale.PREV_LINE_CMD, true);
		addKey(gkcCanvas.KEY_DOWN, keyName(Locale.KEY_DOWN), "D", Locale.NEXT_LINE_CMD, true);
		addKey(gkcCanvas.KEY_LEFT, keyName(Locale.KEY_LEFT), "L", Locale.PREV_SCREEN_CMD, true);
		addKey(gkcCanvas.KEY_RIGHT, keyName(Locale.KEY_RIGHT), "R", Locale.NEXT_SCREEN_CMD, true);
		addKey(gkcCanvas.KEY_FIRE, keyName(Locale.KEY_JOY), "F", Locale.SELECT_CMD, true);

		addNumKey(gkcCanvas.KEY_STAR, Locale.QUICK_SWITCH);
		addNumKey(gkcCanvas.KEY_POUND, Locale.HOT_KEYS);
		addNumKey(gkcCanvas.KEY_NUM0, Locale.CLOCK_MODE);
		addNumKey(gkcCanvas.KEY_NUM1, Locale.PREV_PANEL);
		addNumKey(gkcCanvas.KEY_NUM2, Locale.NEXT_PANEL);
		addNumKey(gkcCanvas.KEY_NUM3, Locale.MEMORY_MONITOR);
		addNumKey(gkcCanvas.KEY_NUM4, Locale.PREV_FREE);
		addNumKey(gkcCanvas.KEY_NUM5, Locale.NEXT_FREE);
		addNumKey(gkcCanvas.KEY_NUM6, Locale.CONTAINERS);
		addNumKey(gkcCanvas.KEY_NUM7, Locale.MARK_ALL_CMD);
		addNumKey(gkcCanvas.KEY_NUM8, Locale.DEMARK_ALL_CMD);
		addNumKey(gkcCanvas.KEY_NUM9, Locale.PANELS);

		addNumKey(gkcCanvas.KEY_STAR | gkcCanvas.KEY_HOT, Locale.MINIMIZE_CMD);
		addNumKey(gkcCanvas.KEY_POUND | gkcCanvas.KEY_HOT, Locale.FULLSCREEN_CMD);
		addNumKey(gkcCanvas.KEY_NUM0 | gkcCanvas.KEY_HOT, Locale.FAVOURITE);
		addNumKey(gkcCanvas.KEY_NUM1 | gkcCanvas.KEY_HOT, Locale.INSERT_CMD);
		addNumKey(gkcCanvas.KEY_NUM2 | gkcCanvas.KEY_HOT, Locale.COPY_CMD);
		addNumKey(gkcCanvas.KEY_NUM3 | gkcCanvas.KEY_HOT, Locale.MOVE_CMD);
		addNumKey(gkcCanvas.KEY_NUM4 | gkcCanvas.KEY_HOT, Locale.DELETE_CMD);
		addNumKey(gkcCanvas.KEY_NUM5 | gkcCanvas.KEY_HOT, Locale.RENAME_CMD);
		addNumKey(gkcCanvas.KEY_NUM6 | gkcCanvas.KEY_HOT, Locale.MENU_SEARCH);
		addNumKey(gkcCanvas.KEY_NUM7 | gkcCanvas.KEY_HOT, Locale.PROPERTY_CMD);
		addNumKey(gkcCanvas.KEY_NUM8 | gkcCanvas.KEY_HOT, Locale.DISK_INFO_CMD);
		addNumKey(gkcCanvas.KEY_NUM9 | gkcCanvas.KEY_HOT, Locale.MODULES_CMD);

		addNumKey(gkcCanvas.KEY_STAR | gkcCanvas.KEY_HELD, Locale.KEYBOARD_CONFIG_CMD);
		addNumKey(gkcCanvas.KEY_POUND | gkcCanvas.KEY_HELD, Locale.COLOR_SCHEME);
		addNumKey(gkcCanvas.KEY_NUM0 | gkcCanvas.KEY_HELD, Locale.TO_FAVOUR_CMD);
		addNumKey(gkcCanvas.KEY_NUM1 | gkcCanvas.KEY_HELD, Locale.SORT_BY_NAME);
		addNumKey(gkcCanvas.KEY_NUM2 | gkcCanvas.KEY_HELD, Locale.SORT_BY_TYPE);
		addNumKey(gkcCanvas.KEY_NUM3 | gkcCanvas.KEY_HELD, Locale.SORT_BY_DATE);
		addNumKey(gkcCanvas.KEY_NUM4 | gkcCanvas.KEY_HELD, Locale.SORT_BY_SIZE);
		addNumKey(gkcCanvas.KEY_NUM5 | gkcCanvas.KEY_HELD, Locale.SORT_REVERSE_ORDER);
		addNumKey(gkcCanvas.KEY_NUM6 | gkcCanvas.KEY_HELD, Locale.IGNORE_CASE);
		addNumKey(gkcCanvas.KEY_NUM7 | gkcCanvas.KEY_HELD, Locale.NEW_FILE_CMD);
		addNumKey(gkcCanvas.KEY_NUM8 | gkcCanvas.KEY_HELD, Locale.NEW_FOLDER_CMD);
		addNumKey(gkcCanvas.KEY_NUM9 | gkcCanvas.KEY_HELD, Locale.CREATE_ARCHIVE);
	}

	protected static void addNumKey(int code, int action)
	{
		String name;

		if((code & gkcCanvas.KEY_HOT) != 0)
		{
			name = String.valueOf((char)code) + HOT_KEY_SUFFIX;
		}
		else if((code & gkcCanvas.KEY_HELD) != 0)
		{
			name = String.valueOf((char)code) + HELD_KEY_SUFFIX;
		}
		else
		{
			name = String.valueOf((char)code);
		}

		addKey(code, name, name, action, true);
	}

	public static String keyName(int name)
	{
		return "#" + Integer.toString(name);
	}
}
