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

package org.jline.reader.impl;

import java.util.ListIterator;
import org.jline.reader.History;
import org.jline.reader.Expander;

public class DefaultExpander implements Expander
{
    @Override
    public String expandHistory(final History history, final String line) {
        boolean inQuote = false;
        final StringBuilder sb = new StringBuilder();
        boolean escaped = false;
        int unicode = 0;
        for (int i = 0; i < line.length(); ++i) {
            char c = line.charAt(i);
            if (unicode > 0) {
                escaped = (--unicode >= 0);
                sb.append(c);
            }
            else if (escaped) {
                if (c == 'u') {
                    unicode = 4;
                }
                else {
                    escaped = false;
                }
                sb.append(c);
            }
            else if (c == '\'') {
                inQuote = !inQuote;
                sb.append(c);
            }
            else if (inQuote) {
                sb.append(c);
            }
            else {
                switch (c) {
                    case '\\': {
                        escaped = true;
                        sb.append(c);
                        break;
                    }
                    case '!': {
                        if (i + 1 < line.length()) {
                            c = line.charAt(++i);
                            boolean neg = false;
                            String rep = null;
                            switch (c) {
                                case '!': {
                                    if (history.size() == 0) {
                                        throw new IllegalArgumentException("!!: event not found");
                                    }
                                    rep = history.get(history.index() - 1);
                                    break;
                                }
                                case '#': {
                                    sb.append(sb.toString());
                                    break;
                                }
                                case '?': {
                                    int i2 = line.indexOf(63, i + 1);
                                    if (i2 < 0) {
                                        i2 = line.length();
                                    }
                                    final String sc = line.substring(i + 1, i2);
                                    i = i2;
                                    final int idx = this.searchBackwards(history, sc, history.index(), false);
                                    if (idx < 0) {
                                        throw new IllegalArgumentException("!?" + sc + ": event not found");
                                    }
                                    rep = history.get(idx);
                                    break;
                                }
                                case '$': {
                                    if (history.size() == 0) {
                                        throw new IllegalArgumentException("!$: event not found");
                                    }
                                    final String previous = history.get(history.index() - 1).trim();
                                    final int lastSpace = previous.lastIndexOf(32);
                                    if (lastSpace != -1) {
                                        rep = previous.substring(lastSpace + 1);
                                        break;
                                    }
                                    rep = previous;
                                    break;
                                }
                                case '\t':
                                case ' ': {
                                    sb.append('!');
                                    sb.append(c);
                                    break;
                                }
                                case '-': {
                                    neg = true;
                                    ++i;
                                }
                                case '0':
                                case '1':
                                case '2':
                                case '3':
                                case '4':
                                case '5':
                                case '6':
                                case '7':
                                case '8':
                                case '9': {
                                    final int i2 = i;
                                    while (i < line.length()) {
                                        c = line.charAt(i);
                                        if (c < '0') {
                                            break;
                                        }
                                        if (c > '9') {
                                            break;
                                        }
                                        ++i;
                                    }
                                    int idx;
                                    try {
                                        idx = Integer.parseInt(line.substring(i2, i));
                                    }
                                    catch (final NumberFormatException e) {
                                        throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i2, i) + ": event not found");
                                    }
                                    if (neg && idx > 0 && idx <= history.size()) {
                                        rep = history.get(history.index() - idx);
                                        break;
                                    }
                                    if (!neg && idx > history.index() - history.size() && idx <= history.index()) {
                                        rep = history.get(idx - 1);
                                        break;
                                    }
                                    throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i2, i) + ": event not found");
                                }
                                default: {
                                    final String ss = line.substring(i);
                                    i = line.length();
                                    final int idx = this.searchBackwards(history, ss, history.index(), true);
                                    if (idx < 0) {
                                        throw new IllegalArgumentException("!" + ss + ": event not found");
                                    }
                                    rep = history.get(idx);
                                    break;
                                }
                            }
                            if (rep != null) {
                                sb.append(rep);
                            }
                            break;
                        }
                        sb.append(c);
                        break;
                    }
                    case '^': {
                        if (i == 0) {
                            final int i3 = line.indexOf(94, i + 1);
                            int i4 = line.indexOf(94, i3 + 1);
                            if (i4 < 0) {
                                i4 = line.length();
                            }
                            if (i3 > 0 && i4 > 0) {
                                final String s1 = line.substring(i + 1, i3);
                                final String s2 = line.substring(i3 + 1, i4);
                                final String s3 = history.get(history.index() - 1).replace(s1, s2);
                                sb.append(s3);
                                i = i4 + 1;
                                break;
                            }
                        }
                        sb.append(c);
                        break;
                    }
                    default: {
                        sb.append(c);
                        break;
                    }
                }
            }
        }
        return sb.toString();
    }
    
    @Override
    public String expandVar(final String word) {
        return word;
    }
    
    protected int searchBackwards(final History history, final String searchTerm, final int startIndex, final boolean startsWith) {
        final ListIterator<History.Entry> it = history.iterator(startIndex);
        while (it.hasPrevious()) {
            final History.Entry e = it.previous();
            if (startsWith) {
                if (e.line().startsWith(searchTerm)) {
                    return e.index();
                }
                continue;
            }
            else {
                if (e.line().contains(searchTerm)) {
                    return e.index();
                }
                continue;
            }
        }
        return -1;
    }
}
