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

package org.jline.utils;

import java.io.IOException;
import java.io.Flushable;
import java.util.ArrayDeque;
import java.io.IOError;
import java.io.StringWriter;

public final class Curses
{
    private static final Object[] sv;
    private static final Object[] dv;
    private static final int IFTE_NONE = 0;
    private static final int IFTE_IF = 1;
    private static final int IFTE_THEN = 2;
    private static final int IFTE_ELSE = 3;
    
    private Curses() {
    }
    
    public static String tputs(final String cap, final Object... params) {
        if (cap != null) {
            final StringWriter sw = new StringWriter();
            tputs(sw, cap, params);
            return sw.toString();
        }
        return null;
    }
    
    public static void tputs(final Appendable out, final String str, final Object... params) {
        try {
            doTputs(out, str, params);
        }
        catch (final Exception e) {
            throw new IOError(e);
        }
    }
    
    private static void doTputs(final Appendable out, final String str, final Object... params) throws IOException {
        int index = 0;
        final int length = str.length();
        int ifte = 0;
        boolean exec = true;
        final ArrayDeque<Object> stack = new ArrayDeque<Object>();
        while (index < length) {
            char ch = str.charAt(index++);
            switch (ch) {
                case '\\': {
                    ch = str.charAt(index++);
                    if (ch >= '0' && ch <= '7') {
                        int val = ch - '0';
                        for (int i = 0; i < 2; ++i) {
                            ch = str.charAt(index++);
                            if (ch < '0' || ch > '7') {
                                throw new IllegalStateException();
                            }
                            val = val * 8 + (ch - '0');
                        }
                        out.append((char)val);
                        continue;
                    }
                    switch (ch) {
                        case 'E':
                        case 'e': {
                            if (exec) {
                                out.append('\u001b');
                                continue;
                            }
                            continue;
                        }
                        case 'n': {
                            out.append('\n');
                            continue;
                        }
                        case 'r': {
                            if (exec) {
                                out.append('\r');
                                continue;
                            }
                            continue;
                        }
                        case 't': {
                            if (exec) {
                                out.append('\t');
                                continue;
                            }
                            continue;
                        }
                        case 'b': {
                            if (exec) {
                                out.append('\b');
                                continue;
                            }
                            continue;
                        }
                        case 'f': {
                            if (exec) {
                                out.append('\f');
                                continue;
                            }
                            continue;
                        }
                        case 's': {
                            if (exec) {
                                out.append(' ');
                                continue;
                            }
                            continue;
                        }
                        case ':':
                        case '\\':
                        case '^': {
                            if (exec) {
                                out.append(ch);
                                continue;
                            }
                            continue;
                        }
                        default: {
                            throw new IllegalArgumentException();
                        }
                    }
                    break;
                }
                case '^': {
                    ch = str.charAt(index++);
                    if (exec) {
                        out.append((char)(ch - '@'));
                        continue;
                    }
                    continue;
                }
                case '%': {
                    ch = str.charAt(index++);
                    switch (ch) {
                        case '%': {
                            if (exec) {
                                out.append('%');
                                continue;
                            }
                            continue;
                        }
                        case 'p': {
                            ch = str.charAt(index++);
                            if (exec) {
                                stack.push(params[ch - '1']);
                                continue;
                            }
                            continue;
                        }
                        case 'P': {
                            ch = str.charAt(index++);
                            if (ch >= 'a' && ch <= 'z') {
                                if (exec) {
                                    Curses.dv[ch - 'a'] = stack.pop();
                                    continue;
                                }
                                continue;
                            }
                            else {
                                if (ch < 'A' || ch > 'Z') {
                                    throw new IllegalArgumentException();
                                }
                                if (exec) {
                                    Curses.sv[ch - 'A'] = stack.pop();
                                    continue;
                                }
                                continue;
                            }
                            break;
                        }
                        case 'g': {
                            ch = str.charAt(index++);
                            if (ch >= 'a' && ch <= 'z') {
                                if (exec) {
                                    stack.push(Curses.dv[ch - 'a']);
                                    continue;
                                }
                                continue;
                            }
                            else {
                                if (ch < 'A' || ch > 'Z') {
                                    throw new IllegalArgumentException();
                                }
                                if (exec) {
                                    stack.push(Curses.sv[ch - 'A']);
                                    continue;
                                }
                                continue;
                            }
                            break;
                        }
                        case '\'': {
                            ch = str.charAt(index++);
                            if (exec) {
                                stack.push((int)ch);
                            }
                            ch = str.charAt(index++);
                            if (ch != '\'') {
                                throw new IllegalArgumentException();
                            }
                            continue;
                        }
                        case '{': {
                            final int start = index;
                            while (str.charAt(index++) != '}') {}
                            if (exec) {
                                final int v = Integer.parseInt(str.substring(start, index - 1));
                                stack.push(v);
                                continue;
                            }
                            continue;
                        }
                        case 'l': {
                            if (exec) {
                                stack.push(stack.pop().toString().length());
                                continue;
                            }
                            continue;
                        }
                        case '+': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 + v2);
                                continue;
                            }
                            continue;
                        }
                        case '-': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 - v2);
                                continue;
                            }
                            continue;
                        }
                        case '*': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 * v2);
                                continue;
                            }
                            continue;
                        }
                        case '/': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 / v2);
                                continue;
                            }
                            continue;
                        }
                        case 'm': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 % v2);
                                continue;
                            }
                            continue;
                        }
                        case '&': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 & v2);
                                continue;
                            }
                            continue;
                        }
                        case '|': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 | v2);
                                continue;
                            }
                            continue;
                        }
                        case '^': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 ^ v2);
                                continue;
                            }
                            continue;
                        }
                        case '=': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 == v2);
                                continue;
                            }
                            continue;
                        }
                        case '>': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 > v2);
                                continue;
                            }
                            continue;
                        }
                        case '<': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 < v2);
                                continue;
                            }
                            continue;
                        }
                        case 'A': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 != 0 && v2 != 0);
                                continue;
                            }
                            continue;
                        }
                        case '!': {
                            if (exec) {
                                final int v4 = toInteger(stack.pop());
                                stack.push(v4 == 0);
                                continue;
                            }
                            continue;
                        }
                        case '~': {
                            if (exec) {
                                final int v4 = toInteger(stack.pop());
                                stack.push(~v4);
                                continue;
                            }
                            continue;
                        }
                        case 'O': {
                            if (exec) {
                                final int v2 = toInteger(stack.pop());
                                final int v3 = toInteger(stack.pop());
                                stack.push(v3 != 0 || v2 != 0);
                                continue;
                            }
                            continue;
                        }
                        case '?': {
                            if (ifte != 0) {
                                throw new IllegalArgumentException();
                            }
                            ifte = 1;
                            continue;
                        }
                        case 't': {
                            if (ifte != 1 && ifte != 3) {
                                throw new IllegalArgumentException();
                            }
                            ifte = 2;
                            exec = (toInteger(stack.pop()) != 0);
                            continue;
                        }
                        case 'e': {
                            if (ifte != 2) {
                                throw new IllegalArgumentException();
                            }
                            ifte = 3;
                            exec = !exec;
                            continue;
                        }
                        case ';': {
                            if (ifte == 0 || ifte == 1) {
                                throw new IllegalArgumentException();
                            }
                            ifte = 0;
                            exec = true;
                            continue;
                        }
                        case 'i': {
                            if (params.length >= 1) {
                                params[0] = toInteger(params[0]) + 1;
                            }
                            if (params.length >= 2) {
                                params[1] = toInteger(params[1]) + 1;
                                continue;
                            }
                            continue;
                        }
                        case 'd': {
                            out.append(Integer.toString(toInteger(stack.pop())));
                            continue;
                        }
                        default: {
                            if (ch == ':') {
                                ch = str.charAt(index++);
                            }
                            boolean alternate = false;
                            boolean left = false;
                            boolean space = false;
                            boolean plus = false;
                            int width = 0;
                            int prec = -1;
                            while ("-+# ".indexOf(ch) >= 0) {
                                switch (ch) {
                                    case '-': {
                                        left = true;
                                        break;
                                    }
                                    case '+': {
                                        plus = true;
                                        break;
                                    }
                                    case '#': {
                                        alternate = true;
                                        break;
                                    }
                                    case ' ': {
                                        space = true;
                                        break;
                                    }
                                }
                                ch = str.charAt(index++);
                            }
                            if ("123456789".indexOf(ch) >= 0) {
                                do {
                                    width = width * 10 + (ch - '0');
                                    ch = str.charAt(index++);
                                } while ("0123456789".indexOf(ch) >= 0);
                            }
                            if (ch == '.') {
                                prec = 0;
                                ch = str.charAt(index++);
                            }
                            if ("0123456789".indexOf(ch) >= 0) {
                                do {
                                    prec = prec * 10 + (ch - '0');
                                    ch = str.charAt(index++);
                                } while ("0123456789".indexOf(ch) >= 0);
                            }
                            if ("cdoxXs".indexOf(ch) < 0) {
                                throw new IllegalArgumentException();
                            }
                            final int cnv = ch;
                            if (exec) {
                                String res;
                                if (cnv == 115) {
                                    res = stack.pop();
                                    if (prec >= 0) {
                                        res = res.substring(0, prec);
                                    }
                                }
                                else {
                                    final int p = toInteger(stack.pop());
                                    final StringBuilder fmt = new StringBuilder(16);
                                    fmt.append('%');
                                    if (alternate) {
                                        fmt.append('#');
                                    }
                                    if (plus) {
                                        fmt.append('+');
                                    }
                                    if (space) {
                                        fmt.append(' ');
                                    }
                                    if (prec >= 0) {
                                        fmt.append('0');
                                        fmt.append(prec);
                                    }
                                    fmt.append((char)cnv);
                                    res = String.format(fmt.toString(), p);
                                }
                                if (width > res.length()) {
                                    res = String.format("%" + (left ? "-" : "") + width + "s", res);
                                }
                                out.append(res);
                                continue;
                            }
                            continue;
                        }
                    }
                    continue;
                }
                case '$': {
                    if (index < length && str.charAt(index) == '<') {
                        int nb = 0;
                        while ((ch = str.charAt(++index)) != '>') {
                            if (ch >= '0' && ch <= '9') {
                                nb = nb * 10 + (ch - '0');
                            }
                            else {
                                if (ch == '*') {
                                    continue;
                                }
                                if (ch == '/') {
                                    continue;
                                }
                                continue;
                            }
                        }
                        ++index;
                        try {
                            if (out instanceof Flushable) {
                                ((Flushable)out).flush();
                            }
                            Thread.sleep(nb);
                        }
                        catch (final InterruptedException ex) {}
                        continue;
                    }
                    if (exec) {
                        out.append(ch);
                        continue;
                    }
                    continue;
                }
                default: {
                    if (exec) {
                        out.append(ch);
                        continue;
                    }
                    continue;
                }
            }
        }
    }
    
    private static int toInteger(final Object pop) {
        if (pop instanceof Number) {
            return ((Number)pop).intValue();
        }
        if (pop instanceof Boolean) {
            return ((boolean)pop) ? 1 : 0;
        }
        return Integer.parseInt(pop.toString());
    }
    
    static {
        sv = new Object[26];
        dv = new Object[26];
    }
}
