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

package com.hypixel.hytale.logger.backend;

import java.util.logging.Level;
import java.io.Writer;
import java.io.PrintWriter;
import java.util.List;
import java.util.function.Consumer;
import java.util.Collection;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import javax.annotation.Nonnull;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.LinkedBlockingQueue;
import javax.annotation.Nullable;
import java.io.OutputStreamWriter;
import java.util.logging.LogRecord;
import java.util.concurrent.BlockingQueue;

public class HytaleConsole extends Thread
{
    public static final String TYPE_DUMB = "dumb";
    public static final HytaleConsole INSTANCE;
    private final BlockingQueue<LogRecord> logRecords;
    private final HytaleLogFormatter formatter;
    @Nullable
    private OutputStreamWriter soutwriter;
    @Nullable
    private OutputStreamWriter serrwriter;
    private String terminalType;
    
    private HytaleConsole() {
        super("HytaleConsole");
        this.logRecords = new LinkedBlockingQueue<LogRecord>();
        this.formatter = new HytaleLogFormatter(this::shouldPrintAnsi);
        this.soutwriter = new OutputStreamWriter(HytaleLoggerBackend.REAL_SOUT, StandardCharsets.UTF_8);
        this.serrwriter = new OutputStreamWriter(HytaleLoggerBackend.REAL_SERR, StandardCharsets.UTF_8);
        this.terminalType = "dumb";
        this.setDaemon(true);
        this.start();
    }
    
    public void publish(@Nonnull final LogRecord logRecord) {
        if (!this.isAlive()) {
            this.publish0(logRecord);
            return;
        }
        this.logRecords.offer(logRecord);
    }
    
    @Override
    public void run() {
        try {
            while (!this.isInterrupted()) {
                this.publish0(this.logRecords.take());
            }
        }
        catch (final InterruptedException ignored) {
            Thread.currentThread().interrupt();
        }
    }
    
    public void shutdown() {
        this.interrupt();
        try {
            this.join();
        }
        catch (final InterruptedException ignored) {
            Thread.currentThread().interrupt();
        }
        final List<LogRecord> list = new ObjectArrayList<LogRecord>();
        this.logRecords.drainTo(list);
        list.forEach(this::publish0);
        if (this.soutwriter != null) {
            try {
                this.soutwriter.flush();
            }
            catch (final Exception ex) {}
            this.soutwriter = null;
        }
        if (this.serrwriter != null) {
            try {
                this.serrwriter.flush();
            }
            catch (final Exception ex2) {}
            this.serrwriter = null;
        }
    }
    
    private void publish0(@Nonnull final LogRecord record) {
        String msg;
        try {
            msg = this.formatter.format(record);
        }
        catch (final Exception ex) {
            if (this.serrwriter != null) {
                ex.printStackTrace(new PrintWriter(this.serrwriter));
            }
            else {
                ex.printStackTrace(System.err);
            }
            return;
        }
        try {
            if (record.getLevel().intValue() >= Level.SEVERE.intValue()) {
                if (this.serrwriter != null) {
                    this.serrwriter.write(msg);
                    try {
                        this.serrwriter.flush();
                    }
                    catch (final Exception ex2) {}
                }
                else {
                    HytaleLoggerBackend.REAL_SERR.print(msg);
                }
            }
            else if (this.soutwriter != null) {
                this.soutwriter.write(msg);
                try {
                    this.soutwriter.flush();
                }
                catch (final Exception ex3) {}
            }
            else {
                HytaleLoggerBackend.REAL_SOUT.print(msg);
            }
        }
        catch (final Exception ex4) {}
    }
    
    public void setTerminal(final String type) {
        this.terminalType = type;
    }
    
    private boolean shouldPrintAnsi() {
        return !"dumb".equals(this.terminalType);
    }
    
    public HytaleLogFormatter getFormatter() {
        return this.formatter;
    }
    
    static {
        INSTANCE = new HytaleConsole();
    }
}
