001/*
002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
003 *
004 *  Permission is hereby granted, free of charge, to any person obtaining
005 *  a copy of this software and associated documentation files (the
006 *  "Software"), to deal in the Software without restriction, including
007 *  without limitation the rights to use, copy, modify, merge, publish,
008 *  distribute, sublicense, and/or sell copies of the Software, and to
009 *  permit persons to whom the Software is furnished to do so, subject to
010 *  the following conditions:
011 *
012 *  The above copyright notice and this permission notice shall be
013 *  included in all copies or substantial portions of the Software.
014 *
015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
022 */
023
024package co.aikar.commands;
025
026import java.util.Arrays;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Locale;
030import java.util.Map;
031
032public class CommandCompletionContext<I extends CommandIssuer> {
033    private final RegisteredCommand command;
034    protected final I issuer;
035    private final String input;
036    private final String config;
037    private final Map<String, String> configs = new HashMap<>();
038    private final List<String> args;
039
040    CommandCompletionContext(RegisteredCommand command, I issuer, String input, String config, String[] args) {
041        this.command = command;
042        this.issuer = issuer;
043        this.input = input;
044        if (config != null) {
045            String[] configs = ACFPatterns.COMMA.split(config);
046            for (String conf : configs) {
047                String[] confsplit = ACFPatterns.EQUALS.split(conf, 2);
048                this.configs.put(confsplit[0].toLowerCase(Locale.ENGLISH), confsplit.length > 1 ? confsplit[1] : null);
049            }
050            this.config = configs[0];
051        } else {
052            this.config = null;
053        }
054
055        this.args = Arrays.asList(args);
056    }
057
058    public Map<String, String> getConfigs() {
059        return configs;
060    }
061
062    public String getConfig(String key) {
063        return getConfig(key, null);
064    }
065
066    public String getConfig(String key, String def) {
067        return this.configs.getOrDefault(key.toLowerCase(Locale.ENGLISH), def);
068    }
069
070    public boolean hasConfig(String key) {
071        return this.configs.containsKey(key.toLowerCase(Locale.ENGLISH));
072    }
073
074    public <T> T getContextValue(Class<? extends T> clazz) throws InvalidCommandArgument {
075        return getContextValue(clazz, null);
076    }
077
078    public <T> T getContextValue(Class<? extends T> clazz, Integer paramIdx) throws InvalidCommandArgument {
079        String name = null;
080        if (paramIdx != null) {
081            if (paramIdx >= command.parameters.length) {
082                throw new IllegalArgumentException("Param index is higher than number of parameters");
083            }
084            CommandParameter param = command.parameters[paramIdx];
085            Class<?> paramType = param.getType();
086            if (!clazz.isAssignableFrom(paramType)) {
087                throw new IllegalArgumentException(param.getName() + ":" + paramType.getName() + " can not satisfy " + clazz.getName());
088            }
089            name = param.getName();
090        } else {
091            CommandParameter[] parameters = command.parameters;
092            for (int i = 0; i < parameters.length; i++) {
093                final CommandParameter parameter = parameters[i];
094                if (clazz.isAssignableFrom(parameter.getType())) {
095                    paramIdx = i;
096                    name = parameter.getName();
097                    break;
098                }
099            }
100            if (paramIdx == null) {
101                throw new IllegalStateException("Can not find any parameter that can satisfy " + clazz.getName());
102            }
103        }
104        return getContextValueByName(clazz, name);
105    }
106
107    public <T> T getContextValueByName(Class<? extends T> clazz, String name) throws InvalidCommandArgument {
108        //noinspection unchecked
109        Map<String, Object> resolved = command.resolveContexts(issuer, args, name);
110        if (resolved == null || !resolved.containsKey(name)) {
111            ACFUtil.sneaky(new CommandCompletionTextLookupException());
112        }
113
114        //noinspection unchecked
115        return (T) resolved.get(name);
116    }
117
118    public CommandIssuer getIssuer() {
119        return issuer;
120    }
121
122    public String getInput() {
123        return input;
124    }
125
126    public String getConfig() {
127        return config;
128    }
129
130    public boolean isAsync() {
131        return CommandManager.getCurrentCommandOperationContext().isAsync();
132    }
133}