/* CVS: $Id: InfoList.java,v 1.7 2001/03/17 11:18:40 gvijf Exp $ */

package evolution;

import java.util.*;

/**
 * A list of information.
 * This type of list is returned from
 * 	World.getSquareInfo()
 * 	World.getHumanInfo()
 * 	World.getConstructionInfo()
 *  World.getActionsInfo()
 *  World.getConstructionsInfo()
 *  World.getResourcesInfo()
 */
public class InfoList {

    /**
     * The formatted String type.
     */
    public static final int STRING = 0;

    /**
     * The Boolean type.
     */
    public static final int BOOLEAN = 1;

    /**
     * The Percentage type.
     */
    public static final int PERCENTAGE = 2;

    /**
     * The Value type.
     */
    public static final int VALUE = 3;

    /**
     * Create a new empty InfoList.
     */
    public InfoList() {
        list = new ArrayList();
        reset();
    }

    /**
     * Reset the iterator.
     */
    public void reset() {
        it = list.iterator();
        e = null;
    }

    /**
     * Iterate to the next element.
     * @return true if the InfoList now points to the next element,
     * false if there are no more elements.
     */
    public boolean next() {
        if(!it.hasNext()) {
            e = null;
            return false;
        }
        e = (Object[]) it.next();
        return true;
    }

    /**
     * Get the name of the current record.
     * @excpetion NoSuchElementException If this InfoList is not pointing
     * to an element.
     */
    public String getName() throws NoSuchElementException {
        if(e == null)
            throw new NoSuchElementException();
        return (String) e[0];
    }

    /**
     * Get the type of the current record.
     * This is one of the public static final fields of this class.
     *    STRING, PERCENTAGE, BOOLEAN, VALUE
     * @excpetion NoSuchElementException If this InfoList is not pointing
     * to an element.
     */
    public int getType() throws NoSuchElementException {
        if(e == null)
            throw new NoSuchElementException();
        return ((Integer) e[1]).intValue();
    }

    /**
     * Get the STRING value of the current record.
     * @excpetion NoSuchElementException If this InfoList is not pointing
     * to an element.
     */
    public String getString() throws NoSuchElementException {
        if(e == null)
            throw new NoSuchElementException();
        return (String) e[2];
    }

    /**
     * Get the PERCENTAGE value of the current record.
     * @excpetion NoSuchElementException If this InfoList is not pointing
     * to an element.
     */
    public double getPercentage() throws NoSuchElementException {
        if(e == null)
            throw new NoSuchElementException();
        return (new Double(getString())).doubleValue();
    }

    /**
     * Get the VALUE value of the current record.
     * @excpetion NoSuchElementException If this InfoList is not pointing
     * to an element.
     */
    public double getValue() throws NoSuchElementException {
        if(e == null)
            throw new NoSuchElementException();
        return (new Double(getString())).doubleValue();
    }

    /**
     * Get the BOOLEAN value of the current record.
     * @excpetion NoSuchElementException If this InfoList is not pointing
     * to an element.
     */
    public boolean getBoolean() throws NoSuchElementException {
        if(e == null)
            throw new NoSuchElementException();
        return (new Boolean(getString())).booleanValue();
    }

    /**
     * Add an element to this InfoList.
     * The list will be reset after the element is added.
     * Precondition: type must be a valid type.
     */
    public void add(String name, int type, String value) {
        list.add(new Object[] {name, new Integer(type), value});
        reset();
    }

    /**
     * Add an element to this InfoList.
     * The list will be reset after the element is added.
     * Precondition: type must be a valid type.
     */
    public void add(String name, int type, boolean value) {
        add(name, type, (value ? bT : bF).toString());
    }

    /**
     * Add an element to this InfoList.
     * The list will be reset after the element is added.
     * Precondition: type must be a valid type.
     */
    public void add(String name, int type, double value) {
        add(name, type, (new Double(value)).toString());
    }

    /**
     * A list which holds all the records in this InfoList.
     */
    private List list;

    /**
     * An iterator on this InfoList.
     */
    private Iterator it;

    /**
     * The record we are currently pointing at.
     */
    private Object[] e = null;

    /**
     * A cached Boolean true value.
     */
    protected static final Boolean bT = new Boolean(true);

    /**
     * A cached Boolean false value.
     */
    protected static final Boolean bF = new Boolean(false);

    /**
     * For debugging, print to stdout.
     */
    public void print() {
        reset();
        while(next()) {
            System.out.print(getName() + "(" + getType() + "): ");
			switch(getType()) {
            	case InfoList.STRING:
                    System.out.println(getString());
            		break;
	            case InfoList.PERCENTAGE:
                    System.out.println(getPercentage());
                	break;
	            case InfoList.BOOLEAN:
                    System.out.println(getBoolean());
                	break;
                case InfoList.VALUE:
                    System.out.println(getValue());
                    break;
                default:
                    System.out.println("[unknown type]");
            }
        }
        reset();
    }

    /**
     * Test program.
     */
    public static void main(String args[]) throws Exception {
        InfoList l = new InfoList();
        l.add("Landtype", InfoList.STRING, "PlainLand");
        l.add("Is transforming?", InfoList.BOOLEAN, true);
        l.add("Transforming to", InfoList.STRING, "Trees");
        l.add("Transformation state", InfoList.PERCENTAGE, 44.5);
        l.print();
    }
}
