001package fr.aumgn.bukkitutils.command.args;
002
003import java.util.Arrays;
004import java.util.Iterator;
005import java.util.List;
006import java.util.Map;
007import java.util.Set;
008
009import fr.aumgn.bukkitutils.command.CommandsMessages;
010import fr.aumgn.bukkitutils.command.arg.CommandArg;
011import fr.aumgn.bukkitutils.command.arg.CommandArgFactory;
012import fr.aumgn.bukkitutils.command.arg.basic.ListArg;
013import fr.aumgn.bukkitutils.command.arg.basic.EnumArg;
014
015public class CommandArgsBase {
016
017    protected final CommandsMessages messages;
018    private final Set<Character> flags;
019    private final Map<Character, String> argsFlags;
020    private final String[] args;
021
022    public CommandArgsBase(CommandsMessages messages, CommandArgsParser parser) {
023        this.messages = messages;
024        this.flags = parser.getFlags();
025        this.argsFlags = parser.getArgsFlags();
026        this.args = parser.getArgs();
027    }
028
029    private boolean hasIndex(int index) {
030        return index < args.length;
031    }
032
033    /**
034     * Checks if the command has flags either
035     * boolean flag or argument flag.
036     */
037    public boolean hasFlags() {
038        return !flags.isEmpty() || !argsFlags.isEmpty();
039    }
040
041    /**
042     * Checks if the commands has the given boolean
043     * flag.
044     */
045    public boolean hasFlag(char character) {
046        return flags.contains(character);
047    }
048
049    /**
050     * Checks if the commands has the given argument
051     * flag.
052     */
053    public boolean hasArgFlag(char character) {
054        return argsFlags.containsKey(character);
055    }
056
057    /**
058     * Returns an iterable over all boolean flags.
059     */
060    public Iterable<Character> flags() {
061        return flags;
062    }
063
064    /**
065     * Returns the number of argument.
066     */
067    public int length() {
068        return args.length;
069    }
070
071    /**
072     * Get the argument at the given position.
073     */
074    public String get(int index) {
075        return args[index];
076    }
077
078    /**
079     * Get the argument at the given position or
080     * the default if argument is omitted.
081     */
082    public String get(int index, String def) {
083        if (hasIndex(index)) {
084            return get(index);
085        }
086
087        return def;
088    }
089
090    /**
091     * Get the given argument flag value.
092     */
093    public String get(char flag) {
094        return argsFlags.get(flag);
095    }
096
097    /**
098     * Get the given argument flag value or
099     * the default if omitted.
100     */
101    public String get(char flag, String def) {
102        if (hasArgFlag(flag)) {
103            return get(flag);
104        }
105
106        return def;
107    }
108
109    protected String getOrNull(int index) {
110        return get(index, (String) null);
111    }
112
113    protected String getOrNull(char flag) {
114        return get(flag, (String) null);
115    }
116
117    /**
118     * Get the {@link CommandArg} corresponding to
119     * the given factory for the given index.
120     */
121    public <T extends CommandArg<?>> T get(int index,
122            CommandArgFactory<T> factory) {
123        return factory.createCommandArg(getOrNull(index));
124    }
125
126    /**
127     * Get the {@link CommandArg} corresponding to
128     * the given factory for the given argument flag.
129     */
130    public <T extends CommandArg<?>> T get(char flag,
131            CommandArgFactory<T> factory) {
132        return factory.createCommandArg(getOrNull(flag));
133    }
134
135    /**
136     * Get the {@link EnumArg} value corresponding to
137     * the given enum class for the given index.
138     */
139    public <T extends Enum<T>> EnumArg<T> get(int index, Class<T> enumClass) {
140        return new EnumArg<T>(messages, getOrNull(index), enumClass);
141    }
142
143    /**
144     * Get the {@link EnumArg} value corresponding to
145     * the given enum class for the given flag.
146     */
147    public <T extends Enum<T>> EnumArg<T> get(char flag, Class<T> enumClass) {
148        return new EnumArg<T>(messages, getOrNull(flag), enumClass);
149    }
150
151    /**
152     * Get the {@link ListArg} wrapping the {@link CommandArg}
153     * corresponding to the given factory for the given index.
154     */
155    public <V, T extends CommandArg<V>> ListArg<V, T> getList(int index,
156            CommandArgFactory<T> factory) {
157        return new ListArg<V, T>(",", factory, getOrNull(index));
158    }
159
160    /**
161     * Get the {@link ListArg} wrapping the {@link CommandArg}
162     * corresponding to the given factory for the given index
163     * using the given separator.
164     */
165    public <V, T extends CommandArg<V>> ListArg<V, T> getList(int index,
166            CommandArgFactory<T> factory, String separator) {
167        return new ListArg<V, T>(separator, factory, getOrNull(index));
168    }
169
170    /**
171     * Get the {@link ListArg} wrapping the {@link CommandArg}
172     * corresponding to the given factory for the given flag.
173     */
174    public <V, T extends CommandArg<V>> ListArg<V, T> getList(char flag,
175            CommandArgFactory<T> factory) {
176        return new ListArg<V, T>(",", factory, getOrNull(flag));
177    }
178
179    /**
180     * Get the {@link ListArg} wrapping the {@link CommandArg}
181     * corresponding to the given factory for the given flag
182     * using the given separator.
183     */
184    public <V, T extends CommandArg<V>> ListArg<V, T> getList(char flag,
185            CommandArgFactory<T> factory, String separator) {
186        return new ListArg<V, T>(separator, factory, getOrNull(flag));
187    }
188
189    private <T extends Enum<T>> CommandArgFactory<EnumArg<T>>
190            enumArgFactory(final Class<T> enumClass) {
191        return new CommandArgFactory<EnumArg<T>>() {
192            @Override
193            public EnumArg<T> createCommandArg(String string) {
194                return new EnumArg<T>(messages, string, enumClass);
195            }
196        };
197    }
198
199    /**
200     * Get the {@link ListArg} wrapping the {@link EnumArg}
201     * corresponding to the given enum class for the given index.
202     */
203    public <T extends Enum<T>> ListArg<T, EnumArg<T>> getList(int index,
204            Class<T> klass) {
205        return new ListArg<T, EnumArg<T>>(",", enumArgFactory(klass),
206                getOrNull(index));
207    }
208
209    /**
210     * Get the {@link ListArg} wrapping the {@link EnumArg}
211     * corresponding to the given enum class for the given index
212     * using the given separator.
213     */
214    public <T extends Enum<T>> ListArg<T, EnumArg<T>> getList(int index,
215            final Class<T> klass, String separator) {
216        return new ListArg<T, EnumArg<T>>(separator, enumArgFactory(klass),
217                getOrNull(index));
218    }
219
220    /**
221     * Get the {@link ListArg} wrapping the {@link EnumArg}
222     * corresponding to the given enum class for the given flag.
223     */
224    public <T extends Enum<T>> ListArg<T, EnumArg<T>> getList(char flag,
225            final Class<T> klass) {
226        return new ListArg<T, EnumArg<T>>(",", enumArgFactory(klass),
227                getOrNull(flag));
228    }
229
230    /**
231     * Get the {@link ListArg} wrapping the {@link EnumArg}
232     * corresponding to the given enum class for the given flag
233     * using the given separator.
234     */
235    public <T extends Enum<T>> ListArg<T, EnumArg<T>> getList(char flag,
236            final Class<T> klass, String separator) {
237        return new ListArg<T, EnumArg<T>>(separator, enumArgFactory(klass),
238                getOrNull(flag));
239    }
240
241    /**
242     * Get the string containing all arguments from index
243     * to endIndex separated by a whitespace.
244     */
245    public String get(int index, int rawEndIndex) {
246        int endIndex;
247        if (rawEndIndex > -1) {
248            endIndex = rawEndIndex;
249        } else {
250            endIndex = args.length - 1;
251        }
252        StringBuilder builder = new StringBuilder();
253        for (int i = index; i < endIndex; i++) {
254            builder.append(args[i]);
255            builder.append(" ");
256        }
257        builder.append(args[endIndex]);
258        return builder.toString();
259    }
260
261    /**
262     * Get the string containing all arguments from index
263     * to endIndex separated by a whitespace or the given default.
264     */
265    public String get(int index, int endIndex, String def) {
266        if (hasIndex(index) && hasIndex(endIndex)) {
267            return get(index, endIndex);
268        }
269
270        return def;
271    }
272
273    /**
274     * Returns all arguments as a list.
275     */
276    public List<String> asList() {
277        return Arrays.asList(args);
278    }
279
280    /**
281     * Returns all arguments starting from index as a list.
282     */
283    public List<String> asList(int index) {
284        return asList(index, args.length - 1);
285    }
286
287    /**
288     * Returns all arguments from index to endIndex
289     * as a list.
290     */
291    public List<String> asList(int index, int endIndex) {
292        int startIndex = Math.max(0, index);
293        int actualEndIndex = Math.min(args.length, endIndex + 1);
294        return asList().subList(startIndex, actualEndIndex);
295    }
296
297    /**
298     * Iterator over all arguments
299     * (does not include argument flags).
300     */
301    public Iterator<String> iterator() {
302        return asList().iterator();
303    }
304}