/*
 * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
 *
 * This software is distributable under the BSD license. See the terms of the
 * BSD license in the documentation provided with this software.
 */
package jline;

import java.util.*;

/**
 *  A {@link Completor} implementation that invokes a child completor
 *  using the appropriate <i>separator</i> argument. This
 *  can be used instead of the individual completors having to
 *  know about argument parsing semantics.
 *  <p>
 *  <strong>Example 1</strong>: Any argument of the command line can
 *  use file completion.
 *  <p>
 *  <pre>
 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link FileNameCompletor} ()))
 *  </pre>
 *  <p>
 *  <strong>Example 2</strong>: The first argument of the command line
 *  can be completed with any of "foo", "bar", or "baz", and remaining
 *  arguments can be completed with a file name.
 *  <p>
 *  <pre>
 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link SimpleCompletor} (new String [] { "foo", "bar", "baz"})));
 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link FileNameCompletor} ()));
 *  </pre>
 *
 *  <p>
 *        When the argument index is past the last embedded completors, the last
 *        completors is always used. To disable this behavior, have the last
 *        completor be a {@link NullCompletor}. For example:
 *        </p>
 *
 *        <pre>
 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link SimpleCompletor} (new String [] { "foo", "bar", "baz"}),
 *                new {@link SimpleCompletor} (new String [] { "xxx", "yyy", "xxx"}),
 *                new {@link NullCompletor}
 *                ));
 *        </pre>
 *  <p>
 *  TODO: handle argument quoting and escape characters
 *  </p>
 *
 *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
 */
public class ArgumentCompletor implements Completor {
    final Completor[] completors;
    final ArgumentDelimiter delim;
    boolean strict = true;

    /**
     *  Constuctor: create a new completor with the default
     *  argument separator of " ".
     *
     *  @param  completor  the embedded completor
     */
    public ArgumentCompletor(final Completor completor) {
        this(new Completor[] {
                 completor
             });
    }

    /**
     *  Constuctor: create a new completor with the default
     *  argument separator of " ".
     *
     *  @param  completors  the List of completors to use
     */
    public ArgumentCompletor(final List completors) {
        this((Completor[]) completors.toArray(new Completor[completors.size()]));
    }

    /**
     *  Constuctor: create a new completor with the default
     *  argument separator of " ".
     *
     *  @param  completors  the embedded argument completors
     */
    public ArgumentCompletor(final Completor[] completors) {
        this(completors, new WhitespaceArgumentDelimiter());
    }

    /**
     *  Constuctor: create a new completor with the specified
     *  argument delimiter.
     *
     *  @param  completor the embedded completor
     *  @param  delim     the delimiter for parsing arguments
     */
    public ArgumentCompletor(final Completor completor,
                             final ArgumentDelimiter delim) {
        this(new Completor[] {
                 completor
             }, delim);
    }

    /**
     *  Constuctor: create a new completor with the specified
     *  argument delimiter.
     *
     *  @param  completors the embedded completors
     *  @param  delim      the delimiter for parsing arguments
     */
    public ArgumentCompletor(final Completor[] completors,
                             final ArgumentDelimiter delim) {
        this.completors = completors;
        this.delim = delim;
    }

    /**
     *  If true, a completion at argument index N will only succeed
     *  if all the completions from 0-(N-1) also succeed.
     */
    public void setStrict(final boolean strict) {
        this.strict = strict;
    }

    /**
     *  Returns whether a completion at argument index N will succees
     *  if all the completions from arguments 0-(N-1) also succeed.
     */
    public boolean getStrict() {
        return this.strict;
    }

    public int complete(final String buffer, final int cursor,
                        final List candidates) {
        ArgumentList list = delim.delimit(buffer, cursor);
        int argpos = list.getArgumentPosition();
        int argIndex = list.getCursorArgumentIndex();

        if (argIndex < 0) {
            return -1;
        }

        final Completor comp;

        // if we are beyond the end of the completors, just use the last one
        if (argIndex >= completors.length) {
            comp = completors[completors.length - 1];
        } else {
            comp = completors[argIndex];
        }

        // ensure that all the previous completors are successful before
        // allowing this completor to pass (only if strict is true).
        for (int i = 0; getStrict() && (i < argIndex); i++) {
            Completor sub =
                completors[(i >= completors.length) ? (completors.length - 1) : i];
            String[] args = list.getArguments();
            String arg = ((args == null) || (i >= args.length)) ? "" : args[i];

            List subCandidates = new LinkedList();

            if (sub.complete(arg, arg.length(), subCandidates) == -1) {
                return -1;
            }

            if (subCandidates.size() == 0) {
                return -1;
            }
        }

        int ret = comp.complete(list.getCursorArgument(), argpos, candidates);

        if (ret == -1) {
            return -1;
        }

        int pos = ret + (list.getBufferPosition() - argpos);

        /**
         *  Special case: when completing in the middle of a line, and the
         *  area under the cursor is a delimiter, then trim any delimiters
         *  from the candidates, since we do not need to have an extra
         *  delimiter.
         *
         *  E.g., if we have a completion for "foo", and we
         *  enter "f bar" into the buffer, and move to after the "f"
         *  and hit TAB, we want "foo bar" instead of "foo  bar".
         */
        if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) {
            for (int i = 0; i < candidates.size(); i++) {
                String val = candidates.get(i).toString();

                while ((val.length() > 0)
                    && delim.isDelimiter(val, val.length() - 1)) {
                    val = val.substring(0, val.length() - 1);
                }

                candidates.set(i, val);
            }
        }

        ConsoleReader.debug("Completing " + buffer + "(pos=" + cursor + ") "
            + "with: " + candidates + ": offset=" + pos);

        return pos;
    }

    /**
     *  The {@link ArgumentCompletor.ArgumentDelimiter} allows custom
     *  breaking up of a {@link String} into individual arguments in
     *  order to dispatch the arguments to the nested {@link Completor}.
     *
     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
     */
    public static interface ArgumentDelimiter {
        /**
         *  Break the specified buffer into individual tokens
         *  that can be completed on their own.
         *
         *  @param  buffer           the buffer to split
         *  @param  argumentPosition the current position of the
         *                           cursor in the buffer
         *  @return                  the tokens
         */
        ArgumentList delimit(String buffer, int argumentPosition);

        /**
         *  Returns true if the specified character is a whitespace
         *  parameter.
         *
         *  @param  buffer the complete command buffer
         *  @param  pos    the index of the character in the buffer
         *  @return        true if the character should be a delimiter
         */
        boolean isDelimiter(String buffer, int pos);
    }

    /**
     *  Abstract implementation of a delimiter that uses the
     *  {@link #isDelimiter} method to determine if a particular
     *  character should be used as a delimiter.
     *
     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
     */
    public abstract static class AbstractArgumentDelimiter
        implements ArgumentDelimiter {
        private char[] quoteChars = new char[] { '\'', '"' };
        private char[] escapeChars = new char[] { '\\' };

        public void setQuoteChars(final char[] quoteChars) {
            this.quoteChars = quoteChars;
        }

        public char[] getQuoteChars() {
            return this.quoteChars;
        }

        public void setEscapeChars(final char[] escapeChars) {
            this.escapeChars = escapeChars;
        }

        public char[] getEscapeChars() {
            return this.escapeChars;
        }

        public ArgumentList delimit(final String buffer, final int cursor) {
            List args = new LinkedList();
            StringBuffer arg = new StringBuffer();
            int argpos = -1;
            int bindex = -1;

            for (int i = 0; (buffer != null) && (i <= buffer.length()); i++) {
                // once we reach the cursor, set the
                // position of the selected index
                if (i == cursor) {
                    bindex = args.size();
                    // the position in the current argument is just the
                    // length of the current argument
                    argpos = arg.length();
                }

                if ((i == buffer.length()) || isDelimiter(buffer, i)) {
                    if (arg.length() > 0) {
                        args.add(arg.toString());
                        arg.setLength(0); // reset the arg
                    }
                } else {
                    arg.append(buffer.charAt(i));
                }
            }

            return new ArgumentList((String[]) args.
                toArray(new String[args.size()]), bindex, argpos, cursor);
        }

        /**
         *  Returns true if the specified character is a whitespace
         *  parameter. Check to ensure that the character is not
         *  escaped by any of
         *  {@link #getQuoteChars}, and is not escaped by ant of the
         *  {@link #getEscapeChars}, and returns true from
         *  {@link #isDelimiterChar}.
         *
         *  @param  buffer the complete command buffer
         *  @param  pos    the index of the character in the buffer
         *  @return        true if the character should be a delimiter
         */
        public boolean isDelimiter(final String buffer, final int pos) {
            if (isQuoted(buffer, pos)) {
                return false;
            }

            if (isEscaped(buffer, pos)) {
                return false;
            }

            return isDelimiterChar(buffer, pos);
        }

        public boolean isQuoted(final String buffer, final int pos) {
            return false;
        }

        public boolean isEscaped(final String buffer, final int pos) {
            if (pos <= 0) {
                return false;
            }

            for (int i = 0; (escapeChars != null) && (i < escapeChars.length);
                     i++) {
                if (buffer.charAt(pos) == escapeChars[i]) {
                    return !isEscaped(buffer, pos - 1); // escape escape
                }
            }

            return false;
        }

        /**
         *  Returns true if the character at the specified position
         *  if a delimiter. This method will only be called if the
         *  character is not enclosed in any of the
         *  {@link #getQuoteChars}, and is not escaped by ant of the
         *  {@link #getEscapeChars}. To perform escaping manually,
         *  override {@link #isDelimiter} instead.
         */
        public abstract boolean isDelimiterChar(String buffer, int pos);
    }

    /**
     *  {@link ArgumentCompletor.ArgumentDelimiter}
     *  implementation that counts all
     *  whitespace (as reported by {@link Character#isWhitespace})
     *  as being a delimiter.
     *
     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
     */
    public static class WhitespaceArgumentDelimiter
        extends AbstractArgumentDelimiter {
        /**
         *  The character is a delimiter if it is whitespace, and the
         *  preceeding character is not an escape character.
         */
        public boolean isDelimiterChar(String buffer, int pos) {
            return Character.isWhitespace(buffer.charAt(pos));
        }
    }

    /**
     *  The result of a delimited buffer.
     *
     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
     */
    public static class ArgumentList {
        private String[] arguments;
        private int cursorArgumentIndex;
        private int argumentPosition;
        private int bufferPosition;

        /**
         *  @param  arguments           the array of tokens
         *  @param  cursorArgumentIndex the token index of the cursor
         *  @param  argumentPosition    the position of the cursor in the
         *                              current token
         *  @param  bufferPosition      the position of the cursor in
         *                              the whole buffer
         */
        public ArgumentList(String[] arguments, int cursorArgumentIndex,
            int argumentPosition, int bufferPosition) {
            this.arguments = arguments;
            this.cursorArgumentIndex = cursorArgumentIndex;
            this.argumentPosition = argumentPosition;
            this.bufferPosition = bufferPosition;
        }

        public void setCursorArgumentIndex(int cursorArgumentIndex) {
            this.cursorArgumentIndex = cursorArgumentIndex;
        }

        public int getCursorArgumentIndex() {
            return this.cursorArgumentIndex;
        }

        public String getCursorArgument() {
            if ((cursorArgumentIndex < 0)
                || (cursorArgumentIndex >= arguments.length)) {
                return null;
            }

            return arguments[cursorArgumentIndex];
        }

        public void setArgumentPosition(int argumentPosition) {
            this.argumentPosition = argumentPosition;
        }

        public int getArgumentPosition() {
            return this.argumentPosition;
        }

        public void setArguments(String[] arguments) {
            this.arguments = arguments;
        }

        public String[] getArguments() {
            return this.arguments;
        }

        public void setBufferPosition(int bufferPosition) {
            this.bufferPosition = bufferPosition;
        }

        public int getBufferPosition() {
            return this.bufferPosition;
        }
    }
}
