001package fr.aumgn.bukkitutils.command.arg.basic;
002
003import java.util.List;
004import java.util.Locale;
005
006import com.google.common.base.Function;
007
008import fr.aumgn.bukkitutils.command.CommandsMessages;
009import fr.aumgn.bukkitutils.command.arg.impl.AbstractCommandArg;
010import fr.aumgn.bukkitutils.command.exception.CommandError;
011import fr.aumgn.bukkitutils.glob.Glob;
012
013public class EnumArg<T extends Enum<T>> extends AbstractCommandArg<T> {
014
015    public static class EnumArgNotFound extends CommandError {
016
017        private static final long serialVersionUID = -3141379222300157186L;
018
019        private static String formatValues(Enum<?>[] values) {
020            if (values.length == 0) {
021                return "";
022            }
023
024            StringBuilder builder = new StringBuilder();
025            builder.append(values[0].name().toLowerCase(Locale.ENGLISH));
026            for (int i = 1; i < values.length; i++) {
027                builder.append(", ");
028                builder.append(values[i].name().toLowerCase(Locale.ENGLISH));
029            }
030
031            return builder.toString();
032        }
033
034        public EnumArgNotFound(CommandsMessages messages,
035                Enum<? extends Enum<?>>[] values) {
036            super(messages.get("enumarg-notfound", formatValues(values)));
037        }
038    }
039
040    public static class MoreThanOneValidValueFound extends CommandError {
041
042        private static final long serialVersionUID = -4412257907548635863L;
043
044        public MoreThanOneValidValueFound(CommandsMessages messages, String name) {
045            super(messages.get("enumarg-morethanonefound", name));
046        }
047    }
048
049    private final CommandsMessages messages;
050    private final Class<T> enumClass;
051
052    public EnumArg(CommandsMessages messages, String string,
053            Class<T> enumClass) {
054        super(string);
055        this.messages = messages;
056        this.enumClass = enumClass;
057    }
058
059    private T[] values() {
060        return enumClass.getEnumConstants();
061    }
062
063    @Override
064    public T value() {
065        List<T> matched = match();
066
067        if (matched.size() > 1) {
068            throw new MoreThanOneValidValueFound(messages, string);
069        }
070
071        return matched.get(0);
072    }
073
074    public List<T> match() {
075        List<T> matched = new Glob(string.toLowerCase(Locale.ENGLISH))
076            .fromStart().build(new Function<T, String>() {
077                @Override
078                public String apply(T value) {
079                    return value.name().toLowerCase(Locale.ENGLISH);
080                }
081            }).filter(values());
082
083        if (matched.isEmpty()) {
084            throw new EnumArgNotFound(messages, values());
085        }
086
087        return matched;
088    }
089}