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

package org.jline.reader.impl;

import java.util.Locale;
import java.util.Iterator;
import java.util.List;
import org.jline.utils.Log;
import org.jline.reader.Reference;
import org.jline.reader.Macro;
import java.util.ArrayList;
import org.jline.terminal.Terminal;
import org.jline.reader.Binding;
import org.jline.keymap.KeyMap;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.jline.reader.LineReader;

public final class InputRC
{
    private final LineReader reader;
    
    public static void configure(final LineReader reader, final URL url) throws IOException {
        try (final InputStream is = url.openStream()) {
            configure(reader, is);
        }
    }
    
    public static void configure(final LineReader reader, final InputStream is) throws IOException {
        try (final InputStreamReader r = new InputStreamReader(is)) {
            configure(reader, r);
        }
    }
    
    public static void configure(final LineReader reader, final Reader r) throws IOException {
        BufferedReader br;
        if (r instanceof BufferedReader) {
            br = (BufferedReader)r;
        }
        else {
            br = new BufferedReader(r);
        }
        final Terminal terminal = reader.getTerminal();
        if ("dumb".equals(terminal.getType()) || "dumb-color".equals(terminal.getType())) {
            reader.getVariables().putIfAbsent("editing-mode", "dumb");
        }
        else {
            reader.getVariables().putIfAbsent("editing-mode", "emacs");
        }
        reader.setKeyMap("main");
        new InputRC(reader).parse(br);
        if ("vi".equals(reader.getVariable("editing-mode"))) {
            reader.getKeyMaps().put("main", reader.getKeyMaps().get("viins"));
        }
        else if ("emacs".equals(reader.getVariable("editing-mode"))) {
            reader.getKeyMaps().put("main", reader.getKeyMaps().get("emacs"));
        }
        else if ("dumb".equals(reader.getVariable("editing-mode"))) {
            reader.getKeyMaps().put("main", reader.getKeyMaps().get("dumb"));
        }
    }
    
    private InputRC(final LineReader reader) {
        this.reader = reader;
    }
    
    private void parse(final BufferedReader br) throws IOException, IllegalArgumentException {
        boolean parsing = true;
        final List<Boolean> ifsStack = new ArrayList<Boolean>();
        String line;
        while ((line = br.readLine()) != null) {
            try {
                line = line.trim();
                if (line.length() == 0) {
                    continue;
                }
                if (line.charAt(0) == '#') {
                    continue;
                }
                int i = 0;
                if (line.charAt(i) == '$') {
                    ++i;
                    while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
                        ++i;
                    }
                    int s = i;
                    while (i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
                        ++i;
                    }
                    final String cmd = line.substring(s, i);
                    while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
                        ++i;
                    }
                    s = i;
                    while (i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
                        ++i;
                    }
                    final String args = line.substring(s, i);
                    if ("if".equalsIgnoreCase(cmd)) {
                        ifsStack.add(parsing);
                        if (!parsing) {
                            continue;
                        }
                        if (args.startsWith("term=")) {
                            continue;
                        }
                        if (args.startsWith("mode=")) {
                            final String mode = (String)this.reader.getVariable("editing-mode");
                            parsing = args.substring("mode=".length()).equalsIgnoreCase(mode);
                        }
                        else {
                            parsing = args.equalsIgnoreCase(this.reader.getAppName());
                        }
                    }
                    else if ("else".equalsIgnoreCase(cmd)) {
                        if (ifsStack.isEmpty()) {
                            throw new IllegalArgumentException("$else found without matching $if");
                        }
                        boolean invert = true;
                        for (final boolean b : ifsStack) {
                            if (!b) {
                                invert = false;
                                break;
                            }
                        }
                        if (!invert) {
                            continue;
                        }
                        parsing = !parsing;
                    }
                    else if ("endif".equalsIgnoreCase(cmd)) {
                        if (ifsStack.isEmpty()) {
                            throw new IllegalArgumentException("endif found without matching $if");
                        }
                        parsing = ifsStack.remove(ifsStack.size() - 1);
                    }
                    else if ("include".equalsIgnoreCase(cmd)) {}
                }
                else {
                    if (!parsing) {
                        continue;
                    }
                    Label_0627: {
                        if (line.charAt(i++) == '\"') {
                            boolean esc = false;
                            while (i < line.length()) {
                                if (esc) {
                                    esc = false;
                                }
                                else if (line.charAt(i) == '\\') {
                                    esc = true;
                                }
                                else if (line.charAt(i) == '\"') {
                                    break Label_0627;
                                }
                                ++i;
                            }
                            throw new IllegalArgumentException("Missing closing quote on line '" + line + "'");
                        }
                    }
                    while (i < line.length() && line.charAt(i) != ':' && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
                        ++i;
                    }
                    String keySeq = line.substring(0, i);
                    final boolean equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '=';
                    ++i;
                    if (equivalency) {
                        ++i;
                    }
                    if (keySeq.equalsIgnoreCase("set")) {
                        while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
                            ++i;
                        }
                        int s2 = i;
                        while (i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
                            ++i;
                        }
                        final String key = line.substring(s2, i);
                        while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
                            ++i;
                        }
                        s2 = i;
                        while (i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
                            ++i;
                        }
                        final String val = line.substring(s2, i);
                        setVar(this.reader, key, val);
                    }
                    else {
                        while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
                            ++i;
                        }
                        final int start = i;
                        if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) {
                            final char delim = line.charAt(i++);
                            boolean esc2 = false;
                            while (i < line.length()) {
                                if (esc2) {
                                    esc2 = false;
                                }
                                else if (line.charAt(i) == '\\') {
                                    esc2 = true;
                                }
                                else if (line.charAt(i) == delim) {
                                    break;
                                }
                                ++i;
                            }
                        }
                        while (i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
                            ++i;
                        }
                        final String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length()));
                        if (keySeq.charAt(0) == '\"') {
                            keySeq = translateQuoted(keySeq);
                        }
                        else {
                            String keyName = (keySeq.lastIndexOf(45) > 0) ? keySeq.substring(keySeq.lastIndexOf(45) + 1) : keySeq;
                            char key2 = getKeyFromName(keyName);
                            keyName = keySeq.toLowerCase();
                            keySeq = "";
                            if (keyName.contains("meta-") || keyName.contains("m-")) {
                                keySeq += "\u001b";
                            }
                            if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) {
                                key2 = (char)(Character.toUpperCase(key2) & '\u001f');
                            }
                            keySeq += key2;
                        }
                        if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) {
                            this.reader.getKeys().bind(new Macro(translateQuoted(val)), keySeq);
                        }
                        else {
                            this.reader.getKeys().bind(new Reference(val), keySeq);
                        }
                    }
                }
            }
            catch (final IllegalArgumentException e) {
                Log.warn("Unable to parse user configuration: ", e);
            }
        }
    }
    
    private static String translateQuoted(final String keySeq) {
        final String str = keySeq.substring(1, keySeq.length() - 1);
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); ++i) {
            char c = str.charAt(i);
            if (c == '\\') {
                final boolean ctrl = str.regionMatches(i, "\\C-", 0, 3) || str.regionMatches(i, "\\M-\\C-", 0, 6);
                final boolean meta = str.regionMatches(i, "\\M-", 0, 3) || str.regionMatches(i, "\\C-\\M-", 0, 6);
                i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + ((!meta && !ctrl) ? 1 : 0);
                if (i >= str.length()) {
                    break;
                }
                c = str.charAt(i);
                if (meta) {
                    sb.append("\u001b");
                }
                if (ctrl) {
                    c = ((c == '?') ? '\u007f' : ((char)(Character.toUpperCase(c) & '\u001f')));
                }
                if (!meta && !ctrl) {
                    switch (c) {
                        case 'a': {
                            c = '\u0007';
                            break;
                        }
                        case 'b': {
                            c = '\b';
                            break;
                        }
                        case 'd': {
                            c = '\u007f';
                            break;
                        }
                        case 'e': {
                            c = '\u001b';
                            break;
                        }
                        case 'f': {
                            c = '\f';
                            break;
                        }
                        case 'n': {
                            c = '\n';
                            break;
                        }
                        case 'r': {
                            c = '\r';
                            break;
                        }
                        case 't': {
                            c = '\t';
                            break;
                        }
                        case 'v': {
                            c = '\u000b';
                            break;
                        }
                        case '\\': {
                            c = '\\';
                            break;
                        }
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7': {
                            c = '\0';
                            for (int j = 0; j < 3; ++j, ++i) {
                                if (i >= str.length()) {
                                    break;
                                }
                                final int k = Character.digit(str.charAt(i), 8);
                                if (k < 0) {
                                    break;
                                }
                                c = (char)(c * '\b' + k);
                            }
                            c &= '\u00ff';
                            break;
                        }
                        case 'x': {
                            ++i;
                            c = '\0';
                            for (int j = 0; j < 2; ++j, ++i) {
                                if (i >= str.length()) {
                                    break;
                                }
                                final int k = Character.digit(str.charAt(i), 16);
                                if (k < 0) {
                                    break;
                                }
                                c = (char)(c * '\u0010' + k);
                            }
                            c &= '\u00ff';
                            break;
                        }
                        case 'u': {
                            ++i;
                            c = '\0';
                            for (int j = 0; j < 4; ++j, ++i) {
                                if (i >= str.length()) {
                                    break;
                                }
                                final int k = Character.digit(str.charAt(i), 16);
                                if (k < 0) {
                                    break;
                                }
                                c = (char)(c * '\u0010' + k);
                            }
                            break;
                        }
                    }
                }
                sb.append(c);
            }
            else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
    
    private static char getKeyFromName(final String name) {
        if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) {
            return '\u007f';
        }
        if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) {
            return '\u001b';
        }
        if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) {
            return '\n';
        }
        if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) {
            return '\r';
        }
        if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) {
            return ' ';
        }
        if ("Tab".equalsIgnoreCase(name)) {
            return '\t';
        }
        return name.charAt(0);
    }
    
    static void setVar(final LineReader reader, final String key, final String val) {
        if ("keymap".equalsIgnoreCase(key)) {
            reader.setKeyMap(val);
            return;
        }
        for (final LineReader.Option option : LineReader.Option.values()) {
            if (option.name().toLowerCase(Locale.ENGLISH).replace('_', '-').equals(val)) {
                if ("on".equalsIgnoreCase(val)) {
                    reader.setOpt(option);
                }
                else if ("off".equalsIgnoreCase(val)) {
                    reader.unsetOpt(option);
                }
                return;
            }
        }
        reader.setVariable(key, val);
    }
}
