package hiro.yoshioka.sdh;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class StringDataHolder {
	// ****************************************************************************
	// public Fields
	// ****************************************************************************

	public static final int NG_VALUE = -1;

	// ****************************************************************************
	// private Fields
	// ****************************************************************************

	private Map<String, List<String>> hash = new HashMap<String, List<String>>();

	String[] key;

	// ****************************************************************************
	// Constructor
	// ****************************************************************************

	public StringDataHolder(String[] argNames) throws NullPointerException {
		if (argNames == null) {
			throw new NullPointerException("argNames must be not null");
		}
		key = argNames;
		for (int iName = 0; iName < argNames.length; iName++) {
			if (argNames[iName] == null) {
				throw new NullPointerException("argNames[" + iName
						+ "] must be not null");
			}
			hash.put(argNames[iName], new ArrayList<String>());
		}
	}

	// ****************************************************************************
	// public methods
	// ****************************************************************************

	public void addData(String argName, int argIndex, String argValue)
			throws IndexOutOfBoundsException, NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		List<String> list = hash.get(argName);
		try {
			list.add(argIndex, argValue);
		} catch (IndexOutOfBoundsException e) {
			throw new IndexOutOfBoundsException("IndexOutOfBoundsException "
					+ argIndex);
		}
	}

	public void setData(String argName, String argValue)
			throws NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		(hash.get(argName)).add(argValue);
	}

	public void setData(String argName, int argIndex, String argValue)
			throws IndexOutOfBoundsException, NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		List<String> list = hash.get(argName);
		if (argIndex < 0 || list.size() < argIndex) {
			throw new IndexOutOfBoundsException("IndexOutOfBoundsException "
					+ argIndex);
		} else if (list.size() == argIndex) {
			list.add(argValue);
		} else {
			list.set(argIndex, argValue);
		}
	}

	public String getData(String argName) throws NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		List<String> list = hash.get(argName);
		return list.get(0);
	}

	public String[][] getAllData() {
		int cnt = getDataCount(key[0]);
		String[][] ret = new String[cnt][key.length];
		for (int irow = 0; irow < cnt; irow++) {
			for (int i = 0; i < key.length; i++) {
				ret[irow][i] = getData(key[i], irow);
			}
		}
		return ret;
	}

	public String getData(String argName, int argIndex)
			throws IndexOutOfBoundsException, NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		List<String> list = hash.get(argName);
		try {
			return list.get(argIndex);
		} catch (IndexOutOfBoundsException e) {
			throw new IndexOutOfBoundsException("IndexOutOfBoundsException "
					+ argIndex);
		}
	}

	public int getMaximumLength(String argName) {
		List<String> list = hash.get(argName);
		int max = 0;
		for (int i = 0; i < list.size(); i++) {
			String value = list.get(i);
			if (max < value.length()) {
				max = value.length();
			}
		}
		return max;
	}

	public int getDataCount(String argName) throws NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		List list = hash.get(argName);
		return list.size();
	}

	public int getDataCount(String[] argName) throws NullPointerException {
		if (argName == null || argName.length <= 0) {
			return NG_VALUE;
		}
		int lastCnt = getDataCount(argName[0]);
		for (int i0 = 1; i0 < argName.length; i0++) {
			if (lastCnt != getDataCount(argName[i0])) {
				return NG_VALUE;
			}
		}
		return lastCnt;
	}

	public void initData(String argName) {
		List list = hash.get(argName);
		if (list == null) {
			return;
		}
		list.clear();
	}

	public void initData() {
		Iterator<String> ite = hash.keySet().iterator();
		while (ite.hasNext()) {
			initData(ite.next());
		}
	}

	public String toString() {
		return hash.toString();
	}

	public boolean contains(String argName, String argValue) {
		List list = hash.get(argName);
		if (list == null) {
			return false;
		}
		return list.contains(argValue);
	}

	public int indexOf(String argName, String argValue) {
		List list = hash.get(argName);
		if (list == null) {
			return NG_VALUE;
		}
		return list.indexOf(argValue);
	}

	public boolean isEmpty(String argName) {
		List list = hash.get(argName);
		if (list == null) {
			return false;
		}
		return list.isEmpty();
	}

	public String remove(String argName, int argIndex)
			throws IndexOutOfBoundsException, NullPointerException {
		if (argName == null) {
			throw new NullPointerException("argName must be not null");
		}
		try {
			return hash.get(argName).remove(argIndex);
		} catch (IndexOutOfBoundsException e) {
			throw new IndexOutOfBoundsException("IndexOutOfBoundsException "
					+ argIndex);
		}
	}

	public int lastIndexOf(String argName, String argValue) {
		List list = hash.get(argName);
		if (list == null) {
			return NG_VALUE;
		}
		return list.lastIndexOf(argValue);
	}

	public String[] getKey() {
		return key;
	}
}