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

package org.jline.console.impl;

import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.reader.Candidate;
import org.jline.reader.impl.completer.ArgumentCompleter;
import org.jline.reader.impl.completer.NullCompleter;
import org.jline.builtins.SyntaxHighlighter;
import java.io.IOException;
import org.jline.builtins.Completers;
import org.jline.reader.Completer;
import java.util.ArrayList;
import java.util.List;
import org.jline.builtins.TTop;
import org.jline.builtins.Commands;
import org.jline.console.CommandInput;
import java.util.Iterator;
import java.util.Map;
import java.util.Collection;
import java.util.HashSet;
import java.util.EnumSet;
import org.jline.console.CommandMethods;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;
import org.jline.reader.LineReader;
import java.nio.file.Path;
import java.util.function.Supplier;
import org.jline.reader.Widget;
import java.util.function.Function;
import org.jline.builtins.ConfigurationPath;
import org.jline.console.CommandRegistry;

public class Builtins extends JlineCommandRegistry implements CommandRegistry
{
    private final ConfigurationPath configPath;
    private final Function<String, Widget> widgetCreator;
    private final Supplier<Path> workDir;
    private LineReader reader;
    
    public Builtins(final Path workDir, final ConfigurationPath configPath, final Function<String, Widget> widgetCreator) {
        this(null, () -> workDir, configPath, widgetCreator);
    }
    
    public Builtins(final Set<Command> commands, final Path workDir, final ConfigurationPath configpath, final Function<String, Widget> widgetCreator) {
        this(commands, () -> workDir, configpath, widgetCreator);
    }
    
    public Builtins(final Supplier<Path> workDir, final ConfigurationPath configPath, final Function<String, Widget> widgetCreator) {
        this(null, workDir, configPath, widgetCreator);
    }
    
    public Builtins(final Set<Command> commands, final Supplier<Path> workDir, final ConfigurationPath configpath, final Function<String, Widget> widgetCreator) {
        Objects.requireNonNull(configpath);
        this.configPath = configpath;
        this.widgetCreator = widgetCreator;
        this.workDir = workDir;
        final Map<Command, String> commandName = new HashMap<Command, String>();
        final Map<Command, CommandMethods> commandExecute = new HashMap<Command, CommandMethods>();
        Set<Command> cmds;
        if (commands == null) {
            cmds = new HashSet<Command>(EnumSet.allOf(Command.class));
        }
        else {
            cmds = new HashSet<Command>(commands);
        }
        for (final Command c : cmds) {
            commandName.put(c, c.name().toLowerCase());
        }
        commandExecute.put(Command.NANO, new CommandMethods(this::nano, this::nanoCompleter));
        commandExecute.put(Command.LESS, new CommandMethods(this::less, this::lessCompleter));
        commandExecute.put(Command.HISTORY, new CommandMethods(this::history, this::historyCompleter));
        commandExecute.put(Command.WIDGET, new CommandMethods(this::widget, this::widgetCompleter));
        commandExecute.put(Command.KEYMAP, new CommandMethods(this::keymap, this::defaultCompleter));
        commandExecute.put(Command.SETOPT, new CommandMethods(this::setopt, this::setoptCompleter));
        commandExecute.put(Command.SETVAR, new CommandMethods(this::setvar, this::setvarCompleter));
        commandExecute.put(Command.UNSETOPT, new CommandMethods(this::unsetopt, this::unsetoptCompleter));
        commandExecute.put(Command.TTOP, new CommandMethods(this::ttop, this::defaultCompleter));
        commandExecute.put(Command.COLORS, new CommandMethods(this::colors, this::defaultCompleter));
        commandExecute.put(Command.HIGHLIGHTER, new CommandMethods(this::highlighter, this::highlighterCompleter));
        this.registerCommands(commandName, commandExecute);
    }
    
    public void setLineReader(final LineReader reader) {
        this.reader = reader;
    }
    
    private void less(final CommandInput input) {
        try {
            Commands.less(input.terminal(), input.in(), input.out(), input.err(), this.workDir.get(), input.xargs(), this.configPath);
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void nano(final CommandInput input) {
        try {
            Commands.nano(input.terminal(), input.out(), input.err(), this.workDir.get(), input.args(), this.configPath);
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void history(final CommandInput input) {
        try {
            Commands.history(this.reader, input.out(), input.err(), this.workDir.get(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void widget(final CommandInput input) {
        try {
            Commands.widget(this.reader, input.out(), input.err(), this.widgetCreator, input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void keymap(final CommandInput input) {
        try {
            Commands.keymap(this.reader, input.out(), input.err(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void setopt(final CommandInput input) {
        try {
            Commands.setopt(this.reader, input.out(), input.err(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void setvar(final CommandInput input) {
        try {
            Commands.setvar(this.reader, input.out(), input.err(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void unsetopt(final CommandInput input) {
        try {
            Commands.unsetopt(this.reader, input.out(), input.err(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void ttop(final CommandInput input) {
        try {
            TTop.ttop(input.terminal(), input.out(), input.err(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void colors(final CommandInput input) {
        try {
            Commands.colors(input.terminal(), input.out(), input.args());
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private void highlighter(final CommandInput input) {
        try {
            Commands.highlighter(this.reader, input.terminal(), input.out(), input.err(), input.args(), this.configPath);
        }
        catch (final Exception e) {
            this.saveException(e);
        }
    }
    
    private List<String> unsetOptions(final boolean set) {
        final List<String> out = new ArrayList<String>();
        for (final LineReader.Option option : LineReader.Option.values()) {
            if (set == (this.reader.isSet(option) == option.isDef())) {
                out.add((option.isDef() ? "no-" : "") + option.toString().toLowerCase().replace('_', '-'));
            }
        }
        return out;
    }
    
    private List<Completer> highlighterCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        final List<Completers.OptDesc> optDescs = this.commandOptions(name);
        for (final Completers.OptDesc o : optDescs) {
            if (o.shortOption() != null && (o.shortOption().equals("-v") || o.shortOption().equals("-s"))) {
                Path userConfig = null;
                if (o.shortOption().equals("-s")) {
                    try {
                        userConfig = this.configPath.getUserConfig("jnanorc");
                    }
                    catch (final IOException ex) {}
                }
                if (!o.shortOption().equals("-v") && userConfig == null) {
                    continue;
                }
                final Path ct = SyntaxHighlighter.build(this.configPath.getConfig("jnanorc"), null).getCurrentTheme();
                if (ct == null) {
                    continue;
                }
                o.setValueCompleter(new Completers.FilesCompleter(ct.getParent(), "*.nanorctheme"));
            }
        }
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new Completers.OptionCompleter(NullCompleter.INSTANCE, optDescs, 1) }));
        return completers;
    }
    
    private Set<String> allWidgets() {
        final Set<String> out = new HashSet<String>();
        for (final String s : this.reader.getWidgets().keySet()) {
            out.add(s);
            out.add(this.reader.getWidgets().get(s).toString());
        }
        return out;
    }
    
    private List<Completer> nanoCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new Completers.OptionCompleter(new Completers.FilesCompleter(this.workDir), (Function<String, Collection<Completers.OptDesc>>)this::commandOptions, 1) }));
        return completers;
    }
    
    private List<Completer> lessCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new Completers.OptionCompleter(new Completers.FilesCompleter(this.workDir), (Function<String, Collection<Completers.OptDesc>>)this::commandOptions, 1) }));
        return completers;
    }
    
    private List<Completer> historyCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        final List<Completers.OptDesc> optDescs = this.commandOptions(name);
        for (final Completers.OptDesc o : optDescs) {
            if (o.shortOption() != null && (o.shortOption().equals("-A") || o.shortOption().equals("-W") || o.shortOption().equals("-R"))) {
                o.setValueCompleter(new Completers.FilesCompleter(this.workDir));
            }
        }
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new Completers.OptionCompleter(NullCompleter.INSTANCE, optDescs, 1) }));
        return completers;
    }
    
    private List<Completer> widgetCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        final List<Completers.OptDesc> optDescs = this.commandOptions(name);
        Candidate aliasOption = new Candidate("-A", "-A", null, null, null, null, true);
        final Iterator<Completers.OptDesc> i = optDescs.iterator();
        while (i.hasNext()) {
            final Completers.OptDesc o = i.next();
            if (o.shortOption() != null) {
                if (o.shortOption().equals("-D")) {
                    o.setValueCompleter(new StringsCompleter(() -> this.reader.getWidgets().keySet()));
                }
                else {
                    if (!o.shortOption().equals("-A")) {
                        continue;
                    }
                    aliasOption = new Candidate(o.shortOption(), o.shortOption(), null, o.description(), null, null, true);
                    i.remove();
                }
            }
        }
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new Completers.OptionCompleter(NullCompleter.INSTANCE, optDescs, 1) }));
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new StringsCompleter(new Candidate[] { aliasOption }), new StringsCompleter((Supplier<Collection<String>>)this::allWidgets), new StringsCompleter(() -> this.reader.getWidgets().keySet()), NullCompleter.INSTANCE }));
        return completers;
    }
    
    private List<Completer> setvarCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new StringsCompleter(() -> this.reader.getVariables().keySet()), NullCompleter.INSTANCE }));
        return completers;
    }
    
    private List<Completer> setoptCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new StringsCompleter(() -> this.unsetOptions(true)) }));
        return completers;
    }
    
    private List<Completer> unsetoptCompleter(final String name) {
        final List<Completer> completers = new ArrayList<Completer>();
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new StringsCompleter(() -> this.unsetOptions(false)) }));
        return completers;
    }
    
    public enum Command
    {
        NANO, 
        LESS, 
        HISTORY, 
        WIDGET, 
        KEYMAP, 
        SETOPT, 
        SETVAR, 
        UNSETOPT, 
        TTOP, 
        COLORS, 
        HIGHLIGHTER;
    }
}
