package org.incava.jagol;

import java.io.*;
import java.util.*;
import org.incava.lang.StringExt;
import org.incava.log.Log;


/**
 * Represents a list of objects that comprise this option.
 */
public class ListOption extends Option
{
    private List value;
    
    /**
     * Creates the option.
     */
    public ListOption(String longName, String description)
    {
        this(longName, description, new ArrayList());
    }

    /**
     * Creates the option, with a default list.
     */
    public ListOption(String longName, String description, List value)
    {
        super(longName, description);
        this.value = value;
    }

    /**
     * Returns the value. This is empty by default.
     */
    public List getValue()
    {
        return value;
    }

    /**
     * Sets the value.
     */
    public void setValue(List value)
    {
        this.value = value;
    }

    /**
     * Sets the value from the string, for a list type. Assumes whitespace or
     * comma delimiter
     */
    public void setValue(String value) throws InvalidTypeException
    {
        Log.log("value: '" + value + "'");
        parse(value);
    }

    /**
     * Sets from a list of command-line arguments. Returns whether this option
     * could be set from the current head of the list. Assumes whitespace or
     * comma delimiter.
     */
    public boolean set(String arg, List args) throws OptionException
    {
        Log.log("arg: " + arg + "; args: " + args);
     
        if (arg.equals("--" + longName)) {
            Log.log("matched long name");

            if (args.size() == 0) {
                throw new InvalidTypeException(longName + " expects following argument");
            }
            else {
                String value = (String)args.remove(0);
                setValue(value);
            }
        }
        else if (arg.startsWith("--" + longName + "=")) {
            Log.log("matched long name + equals");

            // args.remove(0);
            int pos = ("--" + longName + "=").length();
            Log.log("position: " + pos);
            if (pos >= arg.length()) {
                throw new InvalidTypeException(longName + " expects argument");
            }
            else {
                String value = arg.substring(pos);
                setValue(value);
            }
        }
        else if (shortName != 0 && arg.equals("-" + shortName)) {
            Log.log("matched short name");

            if (args.size() == 0) {
                throw new InvalidTypeException(shortName + " expects following argument");
            }
            else {
                String value = (String)args.remove(0);
                setValue(value);
            }
        }
        else {
            Log.log("not a match");
            return false;
        }
        return true;
    }

    /**
     * Parses the value into the value list. If subclasses want to convert the
     * string to their own data type, override the <code>convert</code> method.
     *
     * @see ListOption#convert(String)
     */
    protected void parse(String str) throws InvalidTypeException
    {
        List     list = StringExt.listify(str);
        Iterator it   = list.iterator();
        while (it.hasNext()) {
            String s = (String)it.next();
            if (!s.equals("+=")) {
                value.add(convert(s));
            }
        }
    }

    /**
     * Returns the string, possibly converted to a different Object type. 
     * Subclasses can convert the string to their own data type.
     */
    protected Object convert(String str) throws InvalidTypeException
    {
        return str;
    }

    public String toString()
    {
        StringBuffer buf = new StringBuffer();
        Iterator it = value.iterator();
        boolean isFirst = true;
        while (it.hasNext()) {
            if (isFirst) {
                isFirst = false;
            }
            else {
                buf.append(", ");
            }
            buf.append(it.next());
        }
        return buf.toString();
    }

}
