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

package org.jline.console.impl;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import org.jline.console.ArgDesc;
import java.util.Collections;
import java.util.HashMap;
import org.jline.utils.AttributedString;
import org.jline.reader.impl.completer.ArgumentCompleter;
import java.util.Collection;
import java.util.function.Function;
import org.jline.reader.impl.completer.NullCompleter;
import org.jline.reader.Completer;
import org.jline.builtins.Completers;
import org.jline.console.CmdDesc;
import java.util.ArrayList;
import org.jline.utils.Log;
import org.jline.builtins.Options;
import org.jline.console.CommandRegistry;
import java.util.List;

public abstract class JlineCommandRegistry extends AbstractCommandRegistry
{
    @Override
    public List<String> commandInfo(final String command) {
        try {
            Object[] args = { "--help" };
            if (command.equals("help")) {
                args = new Object[0];
            }
            this.invoke(new CommandRegistry.CommandSession(), command, args);
        }
        catch (final Options.HelpException e) {
            return compileCommandInfo(e.getMessage());
        }
        catch (final Exception e2) {
            Log.info("Error while getting command info", e2);
            if (Log.isDebugEnabled()) {
                e2.printStackTrace();
            }
            return new ArrayList<String>();
        }
        throw new IllegalArgumentException("JlineCommandRegistry.commandInfo() method must be overridden in class " + this.getClass().getCanonicalName());
    }
    
    @Override
    public CmdDesc commandDescription(final List<String> args) {
        final String command = (args != null && !args.isEmpty()) ? args.get(0) : "";
        try {
            this.invoke(new CommandRegistry.CommandSession(), command, "--help");
        }
        catch (final Options.HelpException e) {
            return compileCommandDescription(e.getMessage());
        }
        catch (final Exception ex) {}
        throw new IllegalArgumentException("JlineCommandRegistry.commandDescription() method must be overridden in class " + this.getClass().getCanonicalName());
    }
    
    public List<Completers.OptDesc> commandOptions(final String command) {
        try {
            this.invoke(new CommandRegistry.CommandSession(), command, "--help");
        }
        catch (final Options.HelpException e) {
            return compileCommandOptions(e.getMessage());
        }
        catch (final Exception ex) {}
        return null;
    }
    
    public List<Completer> defaultCompleter(final String command) {
        final List<Completer> completers = new ArrayList<Completer>();
        completers.add(new ArgumentCompleter(new Completer[] { NullCompleter.INSTANCE, new Completers.OptionCompleter(NullCompleter.INSTANCE, (Function<String, Collection<Completers.OptDesc>>)this::commandOptions, 1) }));
        return completers;
    }
    
    public Options parseOptions(final String[] usage, final Object[] args) throws Options.HelpException {
        final Options opt = Options.compile(usage).parse(args);
        if (opt.isSet("help")) {
            throw new Options.HelpException(opt.usage());
        }
        return opt;
    }
    
    private static AttributedString highlightComment(final String comment) {
        return Options.HelpException.highlightComment(comment, Options.HelpException.defaultStyle());
    }
    
    private static String[] helpLines(final String helpMessage, final boolean body) {
        return new HelpLines(helpMessage, body).lines();
    }
    
    public static CmdDesc compileCommandDescription(final String helpMessage) {
        final List<AttributedString> main = new ArrayList<AttributedString>();
        final Map<String, List<AttributedString>> options = new HashMap<String, List<AttributedString>>();
        String prevOpt = null;
        boolean mainDone = false;
        final HelpLines hl = new HelpLines(helpMessage, true);
        for (final String s : hl.lines()) {
            if (s.matches("^\\s+-.*$")) {
                mainDone = true;
                final int ind = s.lastIndexOf("  ");
                if (ind > 0) {
                    final String o = s.substring(0, ind);
                    final String d = s.substring(ind);
                    if (!o.trim().isEmpty()) {
                        prevOpt = o.trim();
                        options.put(prevOpt, new ArrayList<AttributedString>(Collections.singletonList(highlightComment(d.trim()))));
                    }
                }
            }
            else if (s.matches("^[\\s]{20}.*$") && prevOpt != null && options.containsKey(prevOpt)) {
                final int ind = s.lastIndexOf("  ");
                if (ind > 0) {
                    options.get(prevOpt).add(highlightComment(s.substring(ind).trim()));
                }
            }
            else {
                prevOpt = null;
            }
            if (!mainDone) {
                main.add(Options.HelpException.highlightSyntax(s.trim(), Options.HelpException.defaultStyle(), hl.subcommands()));
            }
        }
        return new CmdDesc(main, ArgDesc.doArgNames(Collections.singletonList("")), options);
    }
    
    public static List<Completers.OptDesc> compileCommandOptions(final String helpMessage) {
        final List<Completers.OptDesc> out = new ArrayList<Completers.OptDesc>();
        for (final String s : helpLines(helpMessage, true)) {
            if (s.matches("^\\s+-.*$")) {
                final int ind = s.lastIndexOf("  ");
                if (ind > 0) {
                    final String[] op = s.substring(0, ind).trim().split("\\s+");
                    final String d = s.substring(ind).trim();
                    String so = null;
                    String lo = null;
                    if (op.length == 1) {
                        if (op[0].startsWith("--")) {
                            lo = op[0];
                        }
                        else {
                            so = op[0];
                        }
                    }
                    else {
                        so = op[0];
                        lo = op[1];
                    }
                    boolean hasValue = false;
                    if (lo != null && lo.contains("=")) {
                        hasValue = true;
                        lo = lo.split("=")[0];
                    }
                    out.add(new Completers.OptDesc(so, lo, d, hasValue ? Completers.AnyCompleter.INSTANCE : null));
                }
            }
        }
        return out;
    }
    
    public static List<String> compileCommandInfo(final String helpMessage) {
        final List<String> out = new ArrayList<String>();
        boolean first = true;
        for (final String s : helpLines(helpMessage, false)) {
            if (first && s.contains(" - ")) {
                out.add(s.substring(s.indexOf(" - ") + 3).trim());
            }
            else {
                out.add(s.trim());
            }
            first = false;
        }
        return out;
    }
    
    private static class HelpLines
    {
        private final String helpMessage;
        private final boolean body;
        private boolean subcommands;
        
        public HelpLines(final String helpMessage, final boolean body) {
            this.helpMessage = helpMessage;
            this.body = body;
        }
        
        public String[] lines() {
            String out = "";
            final Matcher tm = Pattern.compile("(^|\\n)(Usage|Summary)(:)").matcher(this.helpMessage);
            if (tm.find()) {
                this.subcommands = tm.group(2).matches("Summary");
                if (this.body) {
                    out = this.helpMessage.substring(tm.end(3));
                }
                else {
                    out = this.helpMessage.substring(0, tm.start(1));
                }
            }
            else if (!this.body) {
                out = this.helpMessage;
            }
            return out.split("\\r?\\n");
        }
        
        public boolean subcommands() {
            return this.subcommands;
        }
    }
}
