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

package org.jline.terminal.impl.jansi;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Properties;
import org.fusesource.jansi.AnsiConsole;
import org.jline.terminal.impl.PosixPtyTerminal;
import java.io.OutputStream;
import java.io.InputStream;
import org.jline.terminal.impl.PosixSysTerminal;
import org.jline.terminal.impl.jansi.win.JansiWinSysTerminal;
import org.jline.utils.OSUtils;
import org.jline.terminal.Terminal;
import java.nio.charset.Charset;
import org.jline.terminal.Size;
import org.jline.terminal.Attributes;
import java.io.IOException;
import org.jline.terminal.impl.jansi.freebsd.FreeBsdNativePty;
import org.jline.terminal.impl.jansi.osx.OsXNativePty;
import org.jline.terminal.impl.jansi.linux.LinuxNativePty;
import org.jline.terminal.spi.Pty;
import org.jline.terminal.spi.SystemStream;
import org.fusesource.jansi.internal.Kernel32;
import org.jline.terminal.spi.TerminalProvider;

public class JansiTerminalProvider implements TerminalProvider
{
    static final int JANSI_MAJOR_VERSION;
    static final int JANSI_MINOR_VERSION;
    
    public static int getJansiMajorVersion() {
        return JansiTerminalProvider.JANSI_MAJOR_VERSION;
    }
    
    public static int getJansiMinorVersion() {
        return JansiTerminalProvider.JANSI_MINOR_VERSION;
    }
    
    public static boolean isAtLeast(final int major, final int minor) {
        return JansiTerminalProvider.JANSI_MAJOR_VERSION > major || (JansiTerminalProvider.JANSI_MAJOR_VERSION == major && JansiTerminalProvider.JANSI_MINOR_VERSION >= minor);
    }
    
    public static void verifyAtLeast(final int major, final int minor) {
        if (!isAtLeast(major, minor)) {
            throw new UnsupportedOperationException("An old version of Jansi is loaded from " + Kernel32.class.getClassLoader().getResource(Kernel32.class.getName().replace('.', '/') + ".class"));
        }
    }
    
    public JansiTerminalProvider() {
        verifyAtLeast(1, 17);
        this.checkIsSystemStream(SystemStream.Output);
    }
    
    @Override
    public String name() {
        return "jansi";
    }
    
    public Pty current(final SystemStream systemStream) throws IOException {
        final String osName = System.getProperty("os.name");
        if (osName.startsWith("Linux")) {
            return LinuxNativePty.current(this, systemStream);
        }
        if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
            return OsXNativePty.current(this, systemStream);
        }
        if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
            throw new UnsupportedOperationException("Unsupported platform " + osName);
        }
        if (osName.startsWith("FreeBSD")) {
            return FreeBsdNativePty.current(this, systemStream);
        }
        throw new UnsupportedOperationException("Unsupported platform " + osName);
    }
    
    public Pty open(final Attributes attributes, final Size size) throws IOException {
        final String osName = System.getProperty("os.name");
        if (osName.startsWith("Linux")) {
            return LinuxNativePty.open(this, attributes, size);
        }
        if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
            return OsXNativePty.open(this, attributes, size);
        }
        if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
            throw new UnsupportedOperationException("Unsupported platform " + osName);
        }
        if (osName.startsWith("FreeBSD")) {
            return FreeBsdNativePty.open(this, attributes, size);
        }
        throw new UnsupportedOperationException("Unsupported platform " + osName);
    }
    
    @Override
    public Terminal sysTerminal(final String name, final String type, final boolean ansiPassThrough, final Charset encoding, final Charset inputEncoding, final Charset outputEncoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler, final boolean paused, final SystemStream systemStream) throws IOException {
        if (OSUtils.IS_WINDOWS) {
            return this.winSysTerminal(name, type, ansiPassThrough, encoding, inputEncoding, outputEncoding, outputEncoding, nativeSignals, signalHandler, paused, systemStream);
        }
        return this.posixSysTerminal(name, type, ansiPassThrough, encoding, inputEncoding, outputEncoding, outputEncoding, nativeSignals, signalHandler, paused, systemStream);
    }
    
    @Deprecated
    @Override
    public Terminal sysTerminal(final String name, final String type, final boolean ansiPassThrough, final Charset encoding, final Charset stdinEncoding, final Charset stdoutEncoding, final Charset stderrEncoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler, final boolean paused, final SystemStream systemStream) throws IOException {
        if (OSUtils.IS_WINDOWS) {
            return this.winSysTerminal(name, type, ansiPassThrough, encoding, stdinEncoding, stdoutEncoding, stderrEncoding, nativeSignals, signalHandler, paused, systemStream);
        }
        return this.posixSysTerminal(name, type, ansiPassThrough, encoding, stdinEncoding, stdoutEncoding, stderrEncoding, nativeSignals, signalHandler, paused, systemStream);
    }
    
    public Terminal winSysTerminal(final String name, final String type, final boolean ansiPassThrough, final Charset encoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler, final boolean paused, final SystemStream systemStream) throws IOException {
        return this.winSysTerminal(name, type, ansiPassThrough, encoding, encoding, encoding, encoding, nativeSignals, signalHandler, paused, systemStream);
    }
    
    public Terminal winSysTerminal(final String name, final String type, final boolean ansiPassThrough, final Charset encoding, final Charset stdinEncoding, final Charset stdoutEncoding, final Charset stderrEncoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler, final boolean paused, final SystemStream systemStream) throws IOException {
        final JansiWinSysTerminal terminal = JansiWinSysTerminal.createTerminal(this, systemStream, name, type, ansiPassThrough, encoding, stdinEncoding, stdoutEncoding, stderrEncoding, nativeSignals, signalHandler, paused);
        terminal.disableScrolling();
        return terminal;
    }
    
    public Terminal posixSysTerminal(final String name, final String type, final boolean ansiPassThrough, final Charset encoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler, final boolean paused, final SystemStream systemStream) throws IOException {
        return this.posixSysTerminal(name, type, ansiPassThrough, encoding, encoding, encoding, encoding, nativeSignals, signalHandler, paused, systemStream);
    }
    
    public Terminal posixSysTerminal(final String name, final String type, final boolean ansiPassThrough, final Charset encoding, final Charset stdinEncoding, final Charset stdoutEncoding, final Charset stderrEncoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler, final boolean paused, final SystemStream systemStream) throws IOException {
        final Pty pty = this.current(systemStream);
        final Charset outputEncoding = (systemStream == SystemStream.Error) ? stderrEncoding : stdoutEncoding;
        return new PosixSysTerminal(name, type, pty, encoding, stdinEncoding, outputEncoding, nativeSignals, signalHandler);
    }
    
    @Override
    public Terminal newTerminal(final String name, final String type, final InputStream in, final OutputStream out, final Charset encoding, final Charset inputEncoding, final Charset outputEncoding, final Terminal.SignalHandler signalHandler, final boolean paused, final Attributes attributes, final Size size) throws IOException {
        final Pty pty = this.open(attributes, size);
        return new PosixPtyTerminal(name, type, pty, in, out, encoding, inputEncoding, outputEncoding, signalHandler, paused);
    }
    
    @Deprecated
    @Override
    public Terminal newTerminal(final String name, final String type, final InputStream in, final OutputStream out, final Charset encoding, final Charset stdinEncoding, final Charset stdoutEncoding, final Charset stderrEncoding, final Terminal.SignalHandler signalHandler, final boolean paused, final Attributes attributes, final Size size) throws IOException {
        final Pty pty = this.open(attributes, size);
        return new PosixPtyTerminal(name, type, pty, in, out, encoding, stdinEncoding, stdoutEncoding, signalHandler, paused);
    }
    
    @Override
    public boolean isSystemStream(final SystemStream stream) {
        try {
            return this.checkIsSystemStream(stream);
        }
        catch (final Throwable t) {
            return false;
        }
    }
    
    private boolean checkIsSystemStream(final SystemStream stream) {
        if (OSUtils.IS_WINDOWS) {
            return JansiWinSysTerminal.isWindowsSystemStream(stream);
        }
        return JansiNativePty.isPosixSystemStream(stream);
    }
    
    @Override
    public String systemStreamName(final SystemStream stream) {
        return JansiNativePty.posixSystemStreamName(stream);
    }
    
    @Override
    public int systemStreamWidth(final SystemStream stream) {
        return JansiNativePty.systemStreamWidth(stream);
    }
    
    @Override
    public String toString() {
        return "TerminalProvider[" + this.name() + "]";
    }
    
    static {
        int major = 0;
        int minor = 0;
        try {
            String v = null;
            try (final InputStream is = AnsiConsole.class.getResourceAsStream("jansi.properties")) {
                if (is != null) {
                    final Properties props = new Properties();
                    props.load(is);
                    v = props.getProperty("version");
                }
            }
            catch (final IOException ex) {}
            if (v == null) {
                v = AnsiConsole.class.getPackage().getImplementationVersion();
            }
            if (v != null) {
                final Matcher m = Pattern.compile("([0-9]+)\\.([0-9]+)([\\.-]\\S+)?").matcher(v);
                if (m.matches()) {
                    major = Integer.parseInt(m.group(1));
                    minor = Integer.parseInt(m.group(2));
                }
            }
        }
        catch (final Throwable t2) {}
        JANSI_MAJOR_VERSION = major;
        JANSI_MINOR_VERSION = minor;
    }
}
