// 
// Decompiled by Procyon v0.6.0
// 

package org.jline.reader.impl.completer;

import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.HashSet;
import java.util.Collection;
import java.util.function.Function;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Iterator;
import org.jline.utils.AttributedString;
import org.jline.reader.Candidate;
import org.jline.reader.ParsedLine;
import org.jline.reader.LineReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jline.reader.Completer;

public class SystemCompleter implements Completer
{
    private Map<String, List<Completer>> completers;
    private Map<String, String> aliasCommand;
    private Map<String, String> descriptions;
    private StringsCompleter commands;
    private boolean compiled;
    
    public SystemCompleter() {
        this.completers = new HashMap<String, List<Completer>>();
        this.aliasCommand = new HashMap<String, String>();
        this.descriptions = new HashMap<String, String>();
        this.compiled = false;
    }
    
    @Override
    public void complete(final LineReader reader, final ParsedLine commandLine, final List<Candidate> candidates) {
        if (!this.compiled) {
            throw new IllegalStateException();
        }
        assert commandLine != null;
        assert candidates != null;
        if (commandLine.words().size() > 0) {
            if (commandLine.words().size() == 1) {
                final String buffer = commandLine.words().get(0);
                final int eq = buffer.indexOf(61);
                if (eq < 0) {
                    this.commands.complete(reader, commandLine, candidates);
                }
                else if (reader.getParser().validVariableName(buffer.substring(0, eq))) {
                    final String curBuf = buffer.substring(0, eq + 1);
                    for (final String c : this.completers.keySet()) {
                        candidates.add(new Candidate(AttributedString.stripAnsi(curBuf + c), c, null, null, null, null, true));
                    }
                }
            }
            else {
                final String cmd = reader.getParser().getCommand(commandLine.words().get(0));
                if (this.command(cmd) != null) {
                    this.completers.get(this.command(cmd)).get(0).complete(reader, commandLine, candidates);
                }
            }
        }
    }
    
    public boolean isCompiled() {
        return this.compiled;
    }
    
    private String command(final String cmd) {
        String out = null;
        if (cmd != null) {
            if (this.completers.containsKey(cmd)) {
                out = cmd;
            }
            else {
                out = this.aliasCommand.get(cmd);
            }
        }
        return out;
    }
    
    public void add(final String command, final List<Completer> completers) {
        for (final Completer c : completers) {
            this.add(command, c);
        }
    }
    
    public void add(final List<String> commands, final Completer completer) {
        for (final String c : commands) {
            this.add(c, completer);
        }
    }
    
    public void add(final String command, final Completer completer) {
        Objects.requireNonNull(command);
        if (this.compiled) {
            throw new IllegalStateException();
        }
        if (!this.completers.containsKey(command)) {
            this.completers.put(command, new ArrayList<Completer>());
        }
        if (completer instanceof ArgumentCompleter) {
            ((ArgumentCompleter)completer).setStrictCommand(false);
        }
        this.completers.get(command).add(completer);
    }
    
    public void add(final SystemCompleter other) {
        if (other.isCompiled()) {
            throw new IllegalStateException();
        }
        for (final Map.Entry<String, List<Completer>> entry : other.getCompleters().entrySet()) {
            for (final Completer c : entry.getValue()) {
                this.add(entry.getKey(), c);
            }
        }
        this.addAliases(other.getAliases());
    }
    
    public void addAliases(final Map<String, String> aliasCommand) {
        if (this.compiled) {
            throw new IllegalStateException();
        }
        this.aliasCommand.putAll(aliasCommand);
    }
    
    private Map<String, String> getAliases() {
        return this.aliasCommand;
    }
    
    public void compile() {
        this.compile(s -> new Candidate(AttributedString.stripAnsi(s), s, null, null, null, null, true));
    }
    
    public void compile(final Function<String, Candidate> candidateBuilder) {
        if (this.compiled) {
            return;
        }
        final Map<String, List<Completer>> compiledCompleters = new HashMap<String, List<Completer>>();
        for (final Map.Entry<String, List<Completer>> entry : this.completers.entrySet()) {
            if (entry.getValue().size() == 1) {
                compiledCompleters.put(entry.getKey(), entry.getValue());
            }
            else {
                compiledCompleters.put(entry.getKey(), new ArrayList<Completer>());
                compiledCompleters.get(entry.getKey()).add((Object)new AggregateCompleter(entry.getValue()));
            }
        }
        this.completers = compiledCompleters;
        final Set<String> cmds = new HashSet<String>(this.completers.keySet());
        cmds.addAll(this.aliasCommand.keySet());
        this.commands = new StringsCompleter((Collection<Candidate>)cmds.stream().map((Function<? super Object, ?>)candidateBuilder).collect((Collector<? super Object, ?, List<? super Object>>)Collectors.toList()));
        this.compiled = true;
    }
    
    public Map<String, List<Completer>> getCompleters() {
        return this.completers;
    }
}
