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

package org.fusesource.jansi;

import java.util.Locale;
import java.io.IOException;
import java.io.IOError;
import java.io.UnsupportedEncodingException;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.charset.Charset;
import org.fusesource.jansi.io.AnsiProcessor;
import org.fusesource.jansi.io.WindowsAnsiProcessor;
import org.fusesource.jansi.internal.MingwSupport;
import org.fusesource.jansi.internal.Kernel32;
import org.fusesource.jansi.io.AnsiOutputStream;
import org.fusesource.jansi.internal.CLibrary;
import java.io.OutputStream;
import org.fusesource.jansi.io.FastBufferedOutputStream;
import java.io.FileOutputStream;
import java.io.FileDescriptor;
import java.io.PrintStream;

public class AnsiConsole
{
    public static final String JANSI_MODE = "jansi.mode";
    public static final String JANSI_OUT_MODE = "jansi.out.mode";
    public static final String JANSI_ERR_MODE = "jansi.err.mode";
    public static final String JANSI_MODE_STRIP = "strip";
    public static final String JANSI_MODE_FORCE = "force";
    public static final String JANSI_MODE_DEFAULT = "default";
    public static final String JANSI_COLORS = "jansi.colors";
    public static final String JANSI_OUT_COLORS = "jansi.out.colors";
    public static final String JANSI_ERR_COLORS = "jansi.err.colors";
    public static final String JANSI_COLORS_16 = "16";
    public static final String JANSI_COLORS_256 = "256";
    public static final String JANSI_COLORS_TRUECOLOR = "truecolor";
    @Deprecated
    public static final String JANSI_PASSTHROUGH = "jansi.passthrough";
    @Deprecated
    public static final String JANSI_STRIP = "jansi.strip";
    @Deprecated
    public static final String JANSI_FORCE = "jansi.force";
    @Deprecated
    public static final String JANSI_EAGER = "jansi.eager";
    public static final String JANSI_NORESET = "jansi.noreset";
    public static final String JANSI_GRACEFUL = "jansi.graceful";
    @Deprecated
    public static PrintStream system_out;
    @Deprecated
    public static PrintStream out;
    @Deprecated
    public static PrintStream system_err;
    @Deprecated
    public static PrintStream err;
    static final boolean IS_WINDOWS;
    static final boolean IS_CYGWIN;
    static final boolean IS_MSYSTEM;
    static final boolean IS_CONEMU;
    static final int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
    static int STDOUT_FILENO;
    static int STDERR_FILENO;
    private static boolean initialized;
    private static int installed;
    private static int virtualProcessing;
    
    public static int getTerminalWidth() {
        int w = out().getTerminalWidth();
        if (w <= 0) {
            w = err().getTerminalWidth();
        }
        return w;
    }
    
    private AnsiConsole() {
    }
    
    private static AnsiPrintStream ansiStream(final boolean stdout) {
        final FileDescriptor descriptor = stdout ? FileDescriptor.out : FileDescriptor.err;
        final OutputStream out = new FastBufferedOutputStream(new FileOutputStream(descriptor));
        String enc = System.getProperty(stdout ? "stdout.encoding" : "stderr.encoding");
        if (enc == null) {
            enc = System.getProperty(stdout ? "sun.stdout.encoding" : "sun.stderr.encoding");
        }
        final int fd = stdout ? AnsiConsole.STDOUT_FILENO : AnsiConsole.STDERR_FILENO;
        boolean isAtty;
        boolean withException;
        try {
            isAtty = (CLibrary.isatty(fd) != 0);
            final String term = System.getenv("TERM");
            final String emacs = System.getenv("INSIDE_EMACS");
            if (isAtty && "dumb".equals(term) && emacs != null && !emacs.contains("comint")) {
                isAtty = false;
            }
            withException = false;
        }
        catch (final Throwable ignore) {
            isAtty = false;
            withException = true;
        }
        final boolean isatty = isAtty;
        AnsiProcessor processor;
        AnsiType type;
        AnsiOutputStream.IoRunnable installer;
        AnsiOutputStream.IoRunnable uninstaller;
        AnsiOutputStream.WidthSupplier width;
        if (!isatty) {
            processor = null;
            type = (withException ? AnsiType.Unsupported : AnsiType.Redirected);
            uninstaller = (installer = null);
            width = new AnsiOutputStream.ZeroWidthSupplier();
        }
        else if (AnsiConsole.IS_WINDOWS) {
            final long console = Kernel32.GetStdHandle(stdout ? Kernel32.STD_OUTPUT_HANDLE : Kernel32.STD_ERROR_HANDLE);
            final int[] mode = { 0 };
            final boolean isConsole = Kernel32.GetConsoleMode(console, mode) != 0;
            final AnsiOutputStream.WidthSupplier kernel32Width = new AnsiOutputStream.WidthSupplier() {
                @Override
                public int getTerminalWidth() {
                    final Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
                    Kernel32.GetConsoleScreenBufferInfo(console, info);
                    return info.windowWidth();
                }
            };
            if (isConsole && Kernel32.SetConsoleMode(console, mode[0] | 0x4) != 0) {
                Kernel32.SetConsoleMode(console, mode[0]);
                processor = null;
                type = AnsiType.VirtualTerminal;
                installer = (() -> {
                    synchronized (AnsiConsole.class) {
                        ++AnsiConsole.virtualProcessing;
                        Kernel32.SetConsoleMode(console, mode[0] | 0x4);
                    }
                    return;
                });
                uninstaller = (() -> {
                    synchronized (AnsiConsole.class) {
                        --AnsiConsole.virtualProcessing;
                        final Object o;
                        if (o == 0) {
                            Kernel32.SetConsoleMode(console, mode[0]);
                        }
                    }
                    return;
                });
                width = kernel32Width;
            }
            else if ((AnsiConsole.IS_CONEMU || AnsiConsole.IS_CYGWIN || AnsiConsole.IS_MSYSTEM) && !isConsole) {
                processor = null;
                type = AnsiType.Native;
                uninstaller = (installer = null);
                final MingwSupport mingw = new MingwSupport();
                final String name = mingw.getConsoleName(stdout);
                if (name != null && !name.isEmpty()) {
                    width = (() -> mingw.getTerminalWidth(name));
                }
                else {
                    width = (() -> -1);
                }
            }
            else {
                AnsiProcessor proc;
                AnsiType ttype;
                try {
                    proc = new WindowsAnsiProcessor(out, console);
                    ttype = AnsiType.Emulation;
                }
                catch (final Throwable ignore2) {
                    proc = new AnsiProcessor(out);
                    ttype = AnsiType.Unsupported;
                }
                processor = proc;
                type = ttype;
                uninstaller = (installer = null);
                width = kernel32Width;
            }
        }
        else {
            processor = null;
            type = AnsiType.Native;
            uninstaller = (installer = null);
            width = new AnsiOutputStream.WidthSupplier() {
                @Override
                public int getTerminalWidth() {
                    final CLibrary.WinSize sz = new CLibrary.WinSize();
                    CLibrary.ioctl(fd, CLibrary.TIOCGWINSZ, sz);
                    return sz.ws_col;
                }
            };
        }
        final String jansiMode = System.getProperty(stdout ? "jansi.out.mode" : "jansi.err.mode", System.getProperty("jansi.mode"));
        AnsiMode mode2;
        if ("force".equals(jansiMode)) {
            mode2 = AnsiMode.Force;
        }
        else if ("strip".equals(jansiMode)) {
            mode2 = AnsiMode.Strip;
        }
        else if (jansiMode != null) {
            mode2 = (isatty ? AnsiMode.Default : AnsiMode.Strip);
        }
        else if (getBoolean("jansi.passthrough")) {
            mode2 = AnsiMode.Force;
        }
        else if (getBoolean("jansi.strip")) {
            mode2 = AnsiMode.Strip;
        }
        else if (getBoolean("jansi.force")) {
            mode2 = AnsiMode.Force;
        }
        else {
            mode2 = (isatty ? AnsiMode.Default : AnsiMode.Strip);
        }
        final String jansiColors = System.getProperty(stdout ? "jansi.out.colors" : "jansi.err.colors", System.getProperty("jansi.colors"));
        AnsiColors colors;
        if ("truecolor".equals(jansiColors)) {
            colors = AnsiColors.TrueColor;
        }
        else if ("256".equals(jansiColors)) {
            colors = AnsiColors.Colors256;
        }
        else if (jansiColors != null) {
            colors = AnsiColors.Colors16;
        }
        else {
            final String colorterm;
            if ((colorterm = System.getenv("COLORTERM")) != null && (colorterm.contains("truecolor") || colorterm.contains("24bit"))) {
                colors = AnsiColors.TrueColor;
            }
            else {
                final String term2;
                if ((term2 = System.getenv("TERM")) != null && term2.contains("-direct")) {
                    colors = AnsiColors.TrueColor;
                }
                else if (term2 != null && term2.contains("-256color")) {
                    colors = AnsiColors.Colors256;
                }
                else {
                    colors = AnsiColors.Colors16;
                }
            }
        }
        final boolean resetAtUninstall = type != AnsiType.Unsupported && !getBoolean("jansi.noreset");
        Charset cs = Charset.defaultCharset();
        if (enc != null) {
            try {
                cs = Charset.forName(enc);
            }
            catch (final UnsupportedCharsetException ex) {}
        }
        return newPrintStream(new AnsiOutputStream(out, width, mode2, processor, type, colors, cs, installer, uninstaller, resetAtUninstall), cs.name());
    }
    
    private static AnsiPrintStream newPrintStream(final AnsiOutputStream out, final String enc) {
        if (enc != null) {
            try {
                return new AnsiPrintStream(out, true, enc);
            }
            catch (final UnsupportedEncodingException ex) {}
        }
        return new AnsiPrintStream(out, true);
    }
    
    static boolean getBoolean(final String name) {
        boolean result = false;
        try {
            final String val = System.getProperty(name);
            result = (val.isEmpty() || Boolean.parseBoolean(val));
        }
        catch (final IllegalArgumentException | NullPointerException ex) {}
        return result;
    }
    
    public static AnsiPrintStream out() {
        initStreams();
        return (AnsiPrintStream)AnsiConsole.out;
    }
    
    public static PrintStream sysOut() {
        return AnsiConsole.system_out;
    }
    
    public static AnsiPrintStream err() {
        initStreams();
        return (AnsiPrintStream)AnsiConsole.err;
    }
    
    public static PrintStream sysErr() {
        return AnsiConsole.system_err;
    }
    
    public static synchronized void systemInstall() {
        if (AnsiConsole.installed == 0) {
            initStreams();
            try {
                ((AnsiPrintStream)AnsiConsole.out).install();
                ((AnsiPrintStream)AnsiConsole.err).install();
            }
            catch (final IOException e) {
                throw new IOError(e);
            }
            System.setOut(AnsiConsole.out);
            System.setErr(AnsiConsole.err);
        }
        ++AnsiConsole.installed;
    }
    
    public static synchronized boolean isInstalled() {
        return AnsiConsole.installed > 0;
    }
    
    public static synchronized void systemUninstall() {
        --AnsiConsole.installed;
        if (AnsiConsole.installed == 0) {
            try {
                ((AnsiPrintStream)AnsiConsole.out).uninstall();
                ((AnsiPrintStream)AnsiConsole.err).uninstall();
            }
            catch (final IOException e) {
                throw new IOError(e);
            }
            AnsiConsole.initialized = false;
            System.setOut(AnsiConsole.system_out);
            System.setErr(AnsiConsole.system_err);
        }
    }
    
    static synchronized void initStreams() {
        if (!AnsiConsole.initialized) {
            AnsiConsole.out = ansiStream(true);
            AnsiConsole.err = ansiStream(false);
            AnsiConsole.initialized = true;
        }
    }
    
    static {
        AnsiConsole.system_out = System.out;
        AnsiConsole.system_err = System.err;
        IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win");
        IS_CYGWIN = (AnsiConsole.IS_WINDOWS && System.getenv("PWD") != null && System.getenv("PWD").startsWith("/"));
        IS_MSYSTEM = (AnsiConsole.IS_WINDOWS && System.getenv("MSYSTEM") != null && (System.getenv("MSYSTEM").startsWith("MINGW") || System.getenv("MSYSTEM").equals("MSYS")));
        IS_CONEMU = (AnsiConsole.IS_WINDOWS && System.getenv("ConEmuPID") != null);
        AnsiConsole.STDOUT_FILENO = 1;
        AnsiConsole.STDERR_FILENO = 2;
        if (getBoolean("jansi.eager")) {
            initStreams();
        }
    }
}
