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

package org.jline.terminal.impl;

import java.util.Iterator;
import org.jline.utils.Signals;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;
import org.jline.utils.FastBufferedOutputStream;
import org.jline.utils.NonBlocking;
import java.util.HashMap;
import java.io.IOException;
import java.nio.charset.Charset;
import org.jline.terminal.spi.Pty;
import org.jline.utils.ShutdownHooks;
import org.jline.terminal.Terminal;
import java.util.Map;
import java.io.PrintWriter;
import org.jline.utils.NonBlockingReader;
import java.io.OutputStream;
import org.jline.utils.NonBlockingInputStream;

public class PosixSysTerminal extends AbstractPosixTerminal
{
    protected final NonBlockingInputStream input;
    protected final OutputStream output;
    protected final NonBlockingReader reader;
    protected final PrintWriter writer;
    protected final Map<Terminal.Signal, Object> nativeHandlers;
    protected final ShutdownHooks.Task closer;
    
    public PosixSysTerminal(final String name, final String type, final Pty pty, final Charset encoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler) throws IOException {
        this(name, type, pty, encoding, encoding, encoding, nativeSignals, signalHandler);
    }
    
    public PosixSysTerminal(final String name, final String type, final Pty pty, final Charset encoding, final Charset inputEncoding, final Charset outputEncoding, final boolean nativeSignals, final Terminal.SignalHandler signalHandler) throws IOException {
        super(name, type, pty, encoding, inputEncoding, outputEncoding, signalHandler);
        this.nativeHandlers = new HashMap<Terminal.Signal, Object>();
        this.input = NonBlocking.nonBlocking(this.getName(), pty.getSlaveInput());
        this.output = new FastBufferedOutputStream(pty.getSlaveOutput());
        this.reader = NonBlocking.nonBlocking(this.getName(), this.input, this.inputEncoding());
        this.writer = new PrintWriter(new OutputStreamWriter(this.output, this.outputEncoding()));
        this.parseInfoCmp();
        if (nativeSignals) {
            for (final Terminal.Signal signal : Terminal.Signal.values()) {
                if (signalHandler == Terminal.SignalHandler.SIG_DFL) {
                    this.nativeHandlers.put(signal, Signals.registerDefault(signal.name()));
                }
                else {
                    this.nativeHandlers.put(signal, Signals.register(signal.name(), () -> this.raise(signal)));
                }
            }
        }
        ShutdownHooks.add(this.closer = this::close);
    }
    
    @Override
    public Terminal.SignalHandler handle(final Terminal.Signal signal, final Terminal.SignalHandler handler) {
        final Terminal.SignalHandler prev = super.handle(signal, handler);
        if (prev != handler) {
            if (handler == Terminal.SignalHandler.SIG_DFL) {
                Signals.registerDefault(signal.name());
            }
            else {
                Signals.register(signal.name(), () -> this.raise(signal));
            }
        }
        return prev;
    }
    
    @Override
    public NonBlockingReader reader() {
        return this.reader;
    }
    
    @Override
    public PrintWriter writer() {
        return this.writer;
    }
    
    @Override
    public InputStream input() {
        return this.input;
    }
    
    @Override
    public OutputStream output() {
        return this.output;
    }
    
    @Override
    protected void doClose() throws IOException {
        this.writer.flush();
        ShutdownHooks.remove(this.closer);
        for (final Map.Entry<Terminal.Signal, Object> entry : this.nativeHandlers.entrySet()) {
            Signals.unregister(entry.getKey().name(), entry.getValue());
        }
        super.doClose();
        this.reader.shutdown();
    }
}
