/*
    Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
    и других спецификаций для функционирования компактных приложений на языке
    Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

    Copyright © 2016–2017, 2019–2022 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package java.io;

import malik.emulator.i18n.*;

public class PrintStream extends OutputStream
{
    private boolean error;
    private final char[] newline;
    private final TextCodec codec;
    private OutputStream out;

    public PrintStream(OutputStream stream) {
        String newline;
        if((newline = System.getProperty("line.separator")) == null) newline = "\n";
        this.newline = newline.toCharArray();
        this.codec = Helper.createTextCodec();
        this.out = stream;
    }

    public void close() {
        OutputStream stream;
        synchronized(newline)
        {
            stream = out;
            out = null;
        }
        if(stream != null)
        {
            try
            {
                stream.close();
            }
            catch(IOException e)
            {
                error = true;
            }
        }
    }

    public void flush() {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        try
        {
            stream.flush();
        }
        catch(IOException e)
        {
            error = true;
        }
    }

    public void write(int byteData) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        try
        {
            stream.write(byteData);
        }
        catch(IOException e)
        {
            error = true;
        }
    }

    public void write(byte[] src, int offset, int length) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        try
        {
            stream.write(src, offset, length);
        }
        catch(IOException e)
        {
            error = true;
        }
    }

    public void print(boolean value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, (value ? "true" : "false").toCharArray());
    }

    public void print(char value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, new char[] { value });
    }

    public void print(float value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, Float.toString(value).toCharArray());
    }

    public void print(double value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, Double.toString(value).toCharArray());
    }

    public void print(int value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, Integer.toString(value, 10).toCharArray());
    }

    public void print(long value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, Long.toString(value, 10).toCharArray());
    }

    public void print(char[] value) {
        OutputStream stream;
        if(value == null)
        {
            throw new NullPointerException("PrintStream.print: аргумент value равен нулевой ссылке.");
        }
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, value);
    }

    public void print(Object value) {
        OutputStream stream;
        String representation;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        if((representation = value == null ? "null" : value.toString()) == null) representation = "null";
        write(stream, representation.toCharArray());
    }

    public void print(String value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, (value == null ? "null" : value).toCharArray());
    }

    public void println() {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        write(stream, newline);
    }

    public void println(boolean value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        writeln(stream, value ? "true" : "false");
    }

    public void println(char value) {
        int lnlen;
        char[] newline;
        char[] characters;
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        (characters = new char[(lnlen = (newline = this.newline).length) + 1])[0] = value;
        Array.copy(newline, 0, characters, 1, lnlen);
        write(stream, characters);
    }

    public void println(float value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        writeln(stream, Float.toString(value));
    }

    public void println(double value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        writeln(stream, Double.toString(value));
    }

    public void println(int value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        writeln(stream, Integer.toString(value, 10));
    }

    public void println(long value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        writeln(stream, Long.toString(value, 10));
    }

    public void println(char[] value) {
        int lnlen;
        int length;
        char[] newline;
        char[] characters;
        OutputStream stream;
        if(value == null)
        {
            throw new NullPointerException("PrintStream.println: аргумент value равен нулевой ссылке.");
        }
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        Array.copy(value, 0, characters = new char[(lnlen = (newline = this.newline).length) + (length = value.length)], 0, length);
        Array.copy(newline, 0, characters, length, lnlen);
        write(stream, characters);
    }

    public void println(Object value) {
        OutputStream stream;
        String representation;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        if((representation = value == null ? "null" : value.toString()) == null) representation = "null";
        writeln(stream, representation);
    }

    public void println(String value) {
        OutputStream stream;
        if((stream = out) == null)
        {
            error = true;
            return;
        }
        writeln(stream, value == null ? "null" : value);
    }

    public boolean checkError() {
        OutputStream stream;
        if((stream = out) == null) return error = true;
        try
        {
            stream.flush();
        }
        catch(IOException e)
        {
            error = true;
        }
        return error;
    }

    protected void setError() {
        error = true;
    }

    private void write(OutputStream stream, char[] characters) {
        byte[] data = codec.encode(characters, 0, characters.length);
        try
        {
            stream.write(data, 0, data.length);
        }
        catch(IOException e)
        {
            error = true;
        }
    }

    private void writeln(OutputStream stream, String representation) {
        int lnlen;
        int length;
        char[] newline;
        char[] characters;
        representation.getChars(0, length = representation.length(), characters = new char[length + (lnlen = (newline = this.newline).length)], 0);
        Array.copy(newline, 0, characters, length, lnlen);
        write(stream, characters);
    }
}
