/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.logging.log4j.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.spi.ExtendedLogger;

/**
 *
 * @since 2.1
 */
public class ByteStreamLogger {
    private class ByteBufferInputStream extends InputStream {

        @Override
        public int read() throws IOException {
            ByteStreamLogger.this.buf.flip();
            int result = -1;
            if (ByteStreamLogger.this.buf.limit() > 0) {
                result = ByteStreamLogger.this.buf.get() & 0xFF;
            }
            ByteStreamLogger.this.buf.compact();
            return result;
        }

        @Override
        public int read(final byte[] bytes, final int off, final int len) throws IOException {
            ByteStreamLogger.this.buf.flip();
            int result = -1;
            if (ByteStreamLogger.this.buf.limit() > 0) {
                result = Math.min(len, ByteStreamLogger.this.buf.limit());
                ByteStreamLogger.this.buf.get(bytes, off, result);
            }
            ByteStreamLogger.this.buf.compact();
            return result;
        }
    }

    private static final int BUFFER_SIZE = 1024;
    private final ExtendedLogger logger;
    private final Level level;
    private final Marker marker;
    private final InputStreamReader reader;
    private final char[] msgBuf = new char[BUFFER_SIZE];
    private final StringBuilder msg = new StringBuilder();
    private boolean closed;

    private final ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);

    public ByteStreamLogger(final ExtendedLogger logger, final Level level, final Marker marker, final Charset charset) {
        this.logger = logger;
        this.level = level == null ? logger.getLevel() : level;
        this.marker = marker;
        this.reader = new InputStreamReader(new ByteBufferInputStream(),
            charset == null ? Charset.defaultCharset() : charset);
    }

    public void close(final String fqcn) {
        synchronized (this.msg) {
            this.closed = true;
            logEnd(fqcn);
        }
    }

    private void extractMessages(final String fqcn) throws IOException {
        if (this.closed) {
            return;
        }
        int read = this.reader.read(this.msgBuf);
        while (read > 0) {
            int off = 0;
            for (int pos = 0; pos < read; pos++) {
                switch (this.msgBuf[pos]) {
                case '\r':
                    this.msg.append(this.msgBuf, off, pos - off);
                    off = pos + 1;
                    break;
                case '\n':
                    this.msg.append(this.msgBuf, off, pos - off);
                    off = pos + 1;
                    log(fqcn);
                    break;
                }
            }
            this.msg.append(this.msgBuf, off, read - off);
            read = this.reader.read(this.msgBuf);
        }
    }

    private void log(final String fqcn) {
        // convert to string now so async loggers work
        this.logger.logIfEnabled(fqcn, this.level, this.marker, this.msg.toString());
        this.msg.setLength(0);
    }

    private void logEnd(final String fqcn) {
        if (this.msg.length() > 0) {
            log(fqcn);
        }
    }

    public void put(final String fqcn, final byte[] b, final int off, final int len) throws IOException {
        int curOff = off;
        int curLen = len;
        if (curLen >= 0) {
            synchronized (this.msg) {
                while (curLen > this.buf.remaining()) {
                    final int remaining = this.buf.remaining();
                    this.buf.put(b, curOff, remaining);
                    curLen -= remaining;
                    curOff += remaining;
                    extractMessages(fqcn);
                }
                this.buf.put(b, curOff, curLen);
                extractMessages(fqcn);
            }
        } else {
            logEnd(fqcn);
        }
    }

    public void put(final String fqcn, final int b) throws IOException {
        if (b >= 0) {
            synchronized (this.msg) {
                this.buf.put((byte) (b & 0xFF));
                extractMessages(fqcn);
            }
        } else {
            logEnd(fqcn);
        }
    }
}
