/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.os;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.util.Formatter;
import java.util.Locale;

import com.android.internal.annotations.VisibleForTesting;

/**
 * A print stream which logs output line by line.
 *
 * {@hide}
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public abstract class LoggingPrintStream extends PrintStream {

    private final StringBuilder builder = new StringBuilder();

    /**
     * A buffer that is initialized when raw bytes are first written to this
     * stream. It may contain the leading bytes of multi-byte characters.
     * Between writes this buffer is always ready to receive data; ie. the
     * position is at the first unassigned byte and the limit is the capacity.
     */
    private ByteBuffer encodedBytes;

    /**
     * A buffer that is initialized when raw bytes are first written to this
     * stream. Between writes this buffer is always clear; ie. the position is
     * zero and the limit is the capacity.
     */
    private CharBuffer decodedChars;

    /**
     * Decodes bytes to characters using the system default charset. Initialized
     * when raw bytes are first written to this stream.
     */
    private CharsetDecoder decoder;

    protected LoggingPrintStream() {
        super(new OutputStream() {
            public void write(int oneByte) throws IOException {
                throw new AssertionError();
            }
        });
    }

    /**
     * Logs the given line.
     */
    protected abstract void log(String line);

    @Override
    public synchronized void flush() {
        flush(true);
    }

    /**
     * Searches buffer for line breaks and logs a message for each one.
     *
     * @param completely true if the ending chars should be treated as a line
     *  even though they don't end in a line break
     */
    private void flush(boolean completely) {
        int length = builder.length();

        int start = 0;
        int nextBreak;

        // Log one line for each line break.
        while (start < length
                && (nextBreak = builder.indexOf("\n", start)) != -1) {
            log(builder.substring(start, nextBreak));
            start = nextBreak + 1;
        }

        if (completely) {
            // Log the remainder of the buffer.
            if (start < length) {
                log(builder.substring(start));
            }
            builder.setLength(0);
        } else {
            // Delete characters leading up to the next starting point.
            builder.delete(0, start);
        }
    }

    public void write(int oneByte) {
        write(new byte[] { (byte) oneByte }, 0, 1);
    }

    @Override
    public void write(byte[] buffer) {
        write(buffer, 0, buffer.length);
    }

    @Override
    public synchronized void write(byte bytes[], int start, int count) {
        if (decoder == null) {
            encodedBytes = ByteBuffer.allocate(80);
            decodedChars = CharBuffer.allocate(80);
            decoder = Charset.defaultCharset().newDecoder()
                    .onMalformedInput(CodingErrorAction.REPLACE)
                    .onUnmappableCharacter(CodingErrorAction.REPLACE);
        }

        int end = start + count;
        while (start < end) {
            // copy some bytes from the array to the long-lived buffer. This
            // way, if we end with a partial character we don't lose it.
            int numBytes = Math.min(encodedBytes.remaining(), end - start);
            encodedBytes.put(bytes, start, numBytes);
            start += numBytes;

            encodedBytes.flip();
            CoderResult coderResult;
            do {
                // decode bytes from the byte buffer into the char buffer
                coderResult = decoder.decode(encodedBytes, decodedChars, false);

                // copy chars from the char buffer into our string builder
                decodedChars.flip();
                builder.append(decodedChars);
                decodedChars.clear();
            } while (coderResult.isOverflow());
            encodedBytes.compact();
        }
        flush(false);
    }

    /** Always returns false. */
    @Override
    public boolean checkError() {
        return false;
    }

    /** Ignored. */
    @Override
    protected void setError() { /* ignored */ }

    /** Ignored. */
    @Override
    public void close() { /* ignored */ }

    @Override
    public PrintStream format(String format, Object... args) {
        return format(Locale.getDefault(), format, args);
    }

    @Override
    public PrintStream printf(String format, Object... args) {
        return format(format, args);
    }

    @Override
    public PrintStream printf(Locale l, String format, Object... args) {
        return format(l, format, args);
    }

    private final Formatter formatter = new Formatter(builder, null);

    @Override
    public synchronized PrintStream format(
            Locale l, String format, Object... args) {
        if (format == null) {
            throw new NullPointerException("format");
        }

        formatter.format(l, format, args);
        flush(false);
        return this;
    }

    @Override
    public synchronized void print(char[] charArray) {
        builder.append(charArray);
        flush(false);
    }

    @Override
    public synchronized void print(char ch) {
        builder.append(ch);
        if (ch == '\n') {
            flush(false);
        }
    }

    @Override
    public synchronized void print(double dnum) {
        builder.append(dnum);
    }

    @Override
    public synchronized void print(float fnum) {
        builder.append(fnum);
    }

    @Override
    public synchronized void print(int inum) {
        builder.append(inum);
    }

    @Override
    public synchronized void print(long lnum) {
        builder.append(lnum);
    }

    @Override
    public synchronized void print(Object obj) {
        builder.append(obj);
        flush(false);
    }

    @Override
    public synchronized void print(String str) {
        builder.append(str);
        flush(false);
    }

    @Override
    public synchronized void print(boolean bool) {
        builder.append(bool);
    }

    @Override
    public synchronized void println() {
        flush(true);
    }

    @Override
    public synchronized void println(char[] charArray) {
        builder.append(charArray);
        flush(true);
    }

    @Override
    public synchronized void println(char ch) {
        builder.append(ch);
        flush(true);
    }

    @Override
    public synchronized void println(double dnum) {
        builder.append(dnum);
        flush(true);
    }

    @Override
    public synchronized void println(float fnum) {
        builder.append(fnum);
        flush(true);
    }

    @Override
    public synchronized void println(int inum) {
        builder.append(inum);
        flush(true);
    }

    @Override
    public synchronized void println(long lnum) {
        builder.append(lnum);
        flush(true);
    }

    @Override
    public synchronized void println(Object obj) {
        builder.append(obj);
        flush(true);
    }

    @Override
    public synchronized void println(String s) {
        if (builder.length() == 0 && s != null) {
            // Optimization for a simple println.
            int length = s.length();

            int start = 0;
            int nextBreak;

            // Log one line for each line break.
            while (start < length
                    && (nextBreak = s.indexOf('\n', start)) != -1) {
                log(s.substring(start, nextBreak));
                start = nextBreak + 1;
            }

            if (start < length) {
                log(s.substring(start));
            }
        } else {
            builder.append(s);
            flush(true);
        }
    }

    @Override
    public synchronized void println(boolean bool) {
        builder.append(bool);
        flush(true);
    }

    @Override
    public synchronized PrintStream append(char c) {
        print(c);
        return this;
    }

    @Override
    public synchronized PrintStream append(CharSequence csq) {
        builder.append(csq);
        flush(false);
        return this;
    }

    @Override
    public synchronized PrintStream append(
            CharSequence csq, int start, int end) {
        builder.append(csq, start, end);
        flush(false);
        return this;
    }
}
