package cnp.ew.util;
import cnp.ew.converter.*;
import java.util.*;

/**
 * Provides a model for the combination of a list of strings and
 * a selection on the strings. Supports direct string lists
 * for now, but should also support an indirect underlying model
 * (use interface instead?).
 */
public class CpStringListAndSelectionModel
    extends CpDefaultObservable
    implements CpConvertibleToString, CpToStringConverter
{
    Vector stringList;
    int selectionIndex;

    public CpStringListAndSelectionModel()
    {
        stringList = new Vector();
        selectionIndex = 0;
    }

    public CpStringListAndSelectionModel(Vector newStringList, int newSelectionIndex)
    {
        setSelectionIndex(newSelectionIndex);
        setStringList(newStringList);
    }

	public int getSelectionIndex()
	{
	    return selectionIndex;
	}

	public String getSelection()
	{
	    return (String)getStringList().elementAt(selectionIndex);
	}

	public void increment()
	{
	    if (selectionIndex == getStringList().size() - 1) {
	        setSelectionIndex(0);
	    } else {
	        setSelectionIndex(selectionIndex + 1);
	    }
	}

	public void decrement()
	{
	    if (selectionIndex == 0) {
	        setSelectionIndex(getStringList().size() - 1);
	    } else {
	        setSelectionIndex(selectionIndex - 1);
	    }
	}

	public void setSelectionIndex(int newSelectionIndex)
	{
	    boolean notify = selectionIndex != newSelectionIndex;
	    selectionIndex = newSelectionIndex;
	    if (notify) {
            notifyObservers (new Integer(selectionIndex));
        }
	}

	public String toString()
    {
        return getSelection();
    }

	public void setSelection(String selection)
	{
	    setSelectionIndex(indexOfString(selection));
	}

	int indexOfString(String string)
	{
	    Vector stringList = getStringList();
	    for (int i= 0; i < stringList.size(); i++) {
	        if (((String)stringList.elementAt(i)).equals(string)) {
	            return i;
	        }
	    }
	    // TBD: throw exception instead
	    return -1;
	}


	public Vector getStringList()
	{
	    // TBD: add support for an indirect model here.
	    return stringList;
	}

	public void setStringList(Vector newStringList)
	{
	    stringList = newStringList;
	    selectionIndex = 0;
        notifyObservers (stringList);
	}

	public void addItem(String s)
	{
	    stringList.addElement(s);
	    notifyObservers(stringList);
	}

	/**
	 * We act as our own converter, to avoid adding
	 * yet another class.  This also means that the
	 * convert() method argument is irrelevant, since
	 * we are the object being converted.
	 */
    public CpToStringConverter converterToString()
    {
        return this;
    }

    /**
     * Convert ourselves into a readable string.  In our case,
     * this means answering the string that is currently selected.
     *
     * Note: since we act as our own converter, we simply do the
     * conversion against ourselves, rather than using the
     * argument passed in.
     */
    public String convert(Object ignore)
    {
        return getSelection();
    }

    /**
     * Set the format string for converting.  For now, we do
     * nothing.  This may prove useful in the future, if we want
     * to apply some text transformation on the stringlist.
     */
    public void setFormatString(String newFormatString)
    {

    }

}