package com.one;

import java.util.*;
import java.io.*;
import com.vmx.*;

/**
 * Парсер INI файлов.
 * Секции подерживаются.
 */
public class IniFile
{
	/*
	 * Здесь собственно данные
	 */
	protected Hashtable sections;
	protected boolean ignorecase;

	/*
	 * Имена секций и ключей в секциях дополнительно помещаются еще и в вектора,
	 * поскольку из Hashtable.keys() они возвращаются вне исходного порядка.
	 */
	protected Vector sectlist;
	protected Hashtable keylists;
	
	/**
	 * Открытие ресурса как INI файла
	 */
	public IniFile(String resname, boolean ignorecase) throws IOException
	{
		read(InputStreamDecoder.getResourceDecoder(resname), ignorecase);
	}
	
	/**
	 * Открытие существующего INI файла
	 */
	public IniFile(InputStreamDecoder isd, boolean ignorecase) throws IOException
	{
		read(isd, ignorecase);
	}
	
	/**
	 * Создание нового INI файла
	 */
	public IniFile(boolean ignorecase)
	{
		sections = new Hashtable();
		this.ignorecase = ignorecase;

		sectlist = new Vector();
		keylists = new Hashtable();
	}
	
	/**
	 * Чтение INI файла
	 */
	public void read(InputStreamDecoder isd, boolean ignorecase) throws IOException
	{
		sections = new Hashtable();
		this.ignorecase = ignorecase;

		sectlist = new Vector();
		keylists = new Hashtable();
		
		String cursection = "";
		Hashtable records = null;
		Vector keylist = null;
		
		String s, key;
		int index;
		
		while((s = isd.readIniLine()) != null)
		{
			index = s.indexOf('=');
			
			if(index >= 0)
			{
				if(records == null)
				{
					records = (Hashtable)sections.get(cursection);
					
					if(records == null)
					{
						records = new Hashtable();
						sections.put(cursection, records);

						keylist = new Vector();
						keylists.put(cursection, keylist);

						sectlist.addElement(cursection);
					}
					else
					{
						keylist = (Vector)keylists.get(cursection);
					}
				}
				
				key = ignorecase ? s.substring(0, index).trim().toLowerCase() : s.substring(0, index).trim();
				
				records.put(key, s.substring(index + 1).trim());
				keylist.addElement(key);
			}
			else
			{
				index = s.indexOf('[');
				
				if(index >= 0)
				{
					s = s.substring(index + 1);
					index = s.indexOf(']');
					
					if(index >= 0)
					{
						cursection = ignorecase ? s.substring(0, index).toLowerCase() : s.substring(0, index);
						records = null;
					}
					else
					{
						if(records == null)
						{
							records = (Hashtable)sections.get(cursection);

							if(records == null)
							{
								records = new Hashtable();
								sections.put(cursection, records);

								keylist = new Vector();
								keylists.put(cursection, keylist);

								sectlist.addElement(cursection);
							}
							else
							{
								keylist = (Vector)keylists.get(cursection);
							}
						}
						
						records.put(s, s);
						keylist.addElement(s);
					}
				}
				else
				{
					if(records == null)
					{
						records = (Hashtable)sections.get(cursection);

						if(records == null)
						{
							records = new Hashtable();
							sections.put(cursection, records);

							keylist = new Vector();
							keylists.put(cursection, keylist);

							sectlist.addElement(cursection);
						}
						else
						{
							keylist = (Vector)keylists.get(cursection);
						}
					}
					
					records.put(s, s);
					keylist.addElement(s);
				}
			}
		}
	}
	
	/**
	 * Запись INI файла
	 */
	public void write(OutputStreamEncoder ose) throws IOException
	{
		String cursection = "";
		Hashtable records = (Hashtable)sections.get(cursection);
		Vector keylist;
		
		Enumeration keys;
		String key;
		String value;
		
		ose.writeBOM();
		
		if(records != null)
		{
			keylist = (Vector)keylists.get(cursection);
			keys = keylist.elements(); // records.keys();
			
			if(keys.hasMoreElements())
			{
				while(keys.hasMoreElements())
				{
					key = (String)keys.nextElement();
					value = (String)records.get(key);
					
					if(value.equals(key))
					{
						ose.writeString(value + "\r\n");
					}
					else
					{
						ose.writeString(key + "\t=\t" + value + "\r\n");
					}
				}
				
				ose.writeString("\r\n");
			}
		}
		
		Enumeration secnames = sectlist.elements(); // sections.keys();
		
		while(secnames.hasMoreElements())
		{
			cursection = (String)secnames.nextElement();
			
			if(cursection.length() == 0)
			{
				continue;
			}
			
			records = (Hashtable)sections.get(cursection);
			keylist = (Vector)keylists.get(cursection);
			keys = keylist.elements(); // records.keys();
			
			if(keys.hasMoreElements())
			{
				ose.writeString("[" + cursection + "]\r\n\r\n");
				
				while(keys.hasMoreElements())
				{
					key = (String)keys.nextElement();
					value = (String)records.get(key);
					
					if(value.equals(key))
					{
						ose.writeString(value + "\r\n");
					}
					else
					{
						ose.writeString(key + "\t=\t" + value + "\r\n");
					}
				}
				
				ose.writeString("\r\n");
			}
		}
	}
	
	public void addRecord(String section, String key, String value)
	{
		if(value == null)
		{
			value = "";
		}
		
		if(key == null || key.length() == 0)
		{
			key = value;
		}
		
		if(section == null)
		{
			section = "";
		}

		if(ignorecase)
		{
			section = section.toLowerCase();
			key = key.toLowerCase();
		}
		
		Hashtable records = (Hashtable)sections.get(section);
		Vector keylist;
		
		if(records == null)
		{
			records = new Hashtable();
			sections.put(section, records);

			keylist = new Vector();
			keylists.put(section, keylist);

			sectlist.addElement(section);
		}
		else
		{
			keylist = (Vector)keylists.get(section);
		}
		
		records.put(key, value);
		keylist.addElement(key);
	}
	
	public String getRecord(String section, String key)
	{
		if(key == null || key.length() == 0)
		{
			return null;
		}
		
		if(section == null)
		{
			section = "";
		}

		if(ignorecase)
		{
			section = section.toLowerCase();
			key = key.toLowerCase();
		}

		Hashtable records = (Hashtable)sections.get(section);
		
		if(records == null)
		{
			return null;
		}
		
		return (String)records.get(key);
	}
	
	public void removeRecord(String section, String key)
	{
		if(section == null)
		{
			section = "";
		}

		if(ignorecase)
		{
			section = section.toLowerCase();
			key = key.toLowerCase();
		}
		
		Hashtable records = (Hashtable)sections.get(section);
		
		if(records != null)
		{
			records.remove(key);
			((Vector)keylists.get(section)).removeElement(key);
		}
	}
	
	public void removeSection(String section)
	{
		if(section == null)
		{
			section = "";
		}

		if(ignorecase)
		{
			section = section.toLowerCase();
		}
		
		sections.remove(section);
		sectlist.removeElement(section);
	}
	
	public Enumeration listSections()
	{
		return sectlist.elements(); // sections.keys();
	}
	
	public Enumeration listKeys(String section)
	{
		if(section == null)
		{
			section = "";
		}

		if(ignorecase)
		{
			section = section.toLowerCase();
		}
		
//		Hashtable records = (Hashtable)sections.get(section);
//
//		if(records == null)
//		{
//			return null;
//		}
//
//		return records.keys();

		Vector keylist = (Vector)keylists.get(section);

		if(keylist == null)
		{
			return null;
		}

		return keylist.elements();
	}
}
