/*
 * 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.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Objects;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LoggingException;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.util.StackLocatorUtil;

/**
 * Builder class to wrap {@link Logger Loggers} into Java IO compatible classes.
 *
 * <p>Both the {@link InputStream}/{@link OutputStream} and {@link Reader}/{@link Writer} family of classes are
 * supported. {@link OutputStream} and {@link Writer} instances can be wrapped by a filtered version of their
 * corresponding classes ({@link java.io.FilterOutputStream} and {@link java.io.FilterWriter}) in order to log all
 * lines written to these instances. {@link InputStream} and {@link Reader} instances can be wrapped by a sort of
 * wiretapped version of their respective classes; all lines read from these instances will be logged.</p>
 *
 * <p>The main feature, however, is the ability to create a {@link PrintWriter}, {@link PrintStream}, {@link Writer},
 * {@link java.io.BufferedWriter}, {@link OutputStream}, or {@link java.io.BufferedOutputStream} that is backed by a
 * {@link Logger}. The main inspiration for this feature is the JDBC API which uses a PrintWriter to perform debug
 * logging. In order to properly integrate APIs like JDBC into Log4j, create a PrintWriter using this class.</p>
 *
 * <p>The IoBuilder support configuration of the logging {@link Level} it should use (defaults to the level of
 * the underlying Logger), and an optional {@link Marker}. The other configurable objects are explained in more
 * detail below.</p>
 *
 * @since 2.1
 */
public class IoBuilder {
    private final ExtendedLogger logger;
    private Level level;
    private Marker marker;
    private String fqcn;
    private boolean autoFlush;
    private boolean buffered;
    private int bufferSize;
    private Charset charset;
    private Reader reader;
    private Writer writer;
    private InputStream inputStream;
    private OutputStream outputStream;

    /**
     * Creates a new builder for a given {@link Logger}. The Logger instance must implement {@link ExtendedLogger} or
     * an exception will be thrown.
     *
     * @param logger the Logger to wrap into a LoggerStream
     * @return a new IoBuilder
     * @throws UnsupportedOperationException if {@code logger} does not implement {@link ExtendedLogger} or if
     *                                       {@code logger} is {@code null}
     */
    public static IoBuilder forLogger(final Logger logger) {
        return new IoBuilder(logger);
    }

    /**
     * Creates a new builder using a Logger name. The name provided is used to get a Logger from
     * {@link LogManager#getLogger(String)} which will be wrapped into a LoggerStream.
     *
     * @param loggerName the name of the Logger to wrap into a LoggerStream
     * @return a new IoBuilder
     */
    public static IoBuilder forLogger(final String loggerName) {
        return new IoBuilder(LogManager.getLogger(loggerName));
    }

    /**
     * Creates a new builder using a Logger named after a given Class. The Class provided is used to get a Logger from
     * {@link LogManager#getLogger(Class)} which will be wrapped into a LoggerStream.
     *
     * @param clazz the Class to use as the Logger name to wrap into a LoggerStream
     * @return a new IoBuilder
     */
    public static IoBuilder forLogger(final Class<?> clazz) {
        return new IoBuilder(LogManager.getLogger(clazz));
    }

    /**
     * Creates a new builder using a Logger named after the calling Class. This is equivalent to the following:
     * <pre>
     *     IoBuilder builder = IoBuilder.forLogger(LogManager.getLogger());
     * </pre>
     *
     * @return a new IoBuilder
     */
    public static IoBuilder forLogger() {
        return new IoBuilder(LogManager.getLogger(StackLocatorUtil.getCallerClass(2)));
    }

    /**
     * Constructs a new IoBuilder for the given Logger. This method is provided for extensibility of this builder
     * class. The static factory methods should be used normally.
     *
     * @param logger the {@link ExtendedLogger} to wrap
     */
    protected IoBuilder(final Logger logger) {
        if (!(logger instanceof ExtendedLogger)) {
            throw new UnsupportedOperationException("The provided Logger [" + String.valueOf(logger) +
                "] does not implement " + ExtendedLogger.class.getName());
        }
        this.logger = (ExtendedLogger) logger;
    }

    /**
     * Specifies the {@link Level} to log at. If no Level is configured, then the Level of the wrapped Logger will be
     * used.
     *
     * @param level the Level to use for logging
     * @return {@code this}
     */
    public IoBuilder setLevel(final Level level) {
        this.level = level;
        return this;
    }

    /**
     * Specifies an optional {@link Marker} to use in all logging messages. If no Marker is specified, then no Marker
     * will be used.
     *
     * @param marker the Marker to associate with all logging messages
     * @return {@code this}
     */
    public IoBuilder setMarker(final Marker marker) {
        this.marker = marker;
        return this;
    }

    /**
     * Specifies the fully qualified class name of the IO wrapper class implementation. This method should only be
     * used when making significant extensions to the provided classes in this component and is normally unnecessary.
     *
     * @param fqcn the fully qualified class name of the IO wrapper class being built
     * @return {@code this}
     */
    public IoBuilder setWrapperClassName(final String fqcn) {
        this.fqcn = fqcn;
        return this;
    }

    /**
     * Indicates whether or not a built {@link PrintWriter} or {@link PrintStream} should automatically flush when
     * one of the {@code println}, {@code printf}, or {@code format} methods are invoked, or when a new line character
     * is printed.
     *
     * @param autoFlush if {@code true}, then {@code println}, {@code printf}, and {@code format} will auto flush
     * @return {@code this}
     */
    public IoBuilder setAutoFlush(final boolean autoFlush) {
        this.autoFlush = autoFlush;
        return this;
    }

    /**
     * Enables or disables using a buffered variant of the desired IO class. If this is set to {@code true}, then the
     * instances returned by {@link #buildReader()} and {@link #buildInputStream()} can be safely cast (if necessary)
     * to {@link java.io.BufferedReader} and {@link java.io.BufferedInputStream} respectively. This option does not
     * have any effect on the other built variants.
     *
     * @param buffered indicates whether or not a wrapped {@link InputStream} or {@link Reader} should be buffered
     * @return {@code this}
     */
    public IoBuilder setBuffered(final boolean buffered) {
        this.buffered = buffered;
        return this;
    }

    /**
     * Configures the buffer size to use when building a {@link java.io.BufferedReader} or
     * {@link java.io.BufferedInputStream} LoggerStream.
     *
     * @param bufferSize the buffer size to use or a non-positive integer to use the default size
     * @return {@code this}
     */
    public IoBuilder setBufferSize(final int bufferSize) {
        this.bufferSize = bufferSize;
        return this;
    }

    /**
     * Specifies the character set to use when building an {@link InputStream}, {@link OutputStream}, or
     * {@link PrintStream}. If no character set is specified, then {@link java.nio.charset.Charset#defaultCharset()}
     * is used.
     *
     * @param charset the character set to use when building an InputStream, OutputStream, or PrintStream
     * @return {@code this}
     */
    public IoBuilder setCharset(final Charset charset) {
        this.charset = charset;
        return this;
    }

    /**
     * Configures a {@link Reader} to be wiretapped when building a Reader. This must be set to a non-{@code null}
     * value in order to call {@link #buildReader()}.
     *
     * @param reader the Reader to wiretap
     * @return {@code this}
     */
    public IoBuilder filter(final Reader reader) {
        this.reader = reader;
        return this;
    }

    /**
     * Configures a {@link Writer} to be written to in addition to the underlying Logger. If no Writer is specified,
     * then the built Writer or PrintWriter will only write to the underlying Logger.
     *
     * @param writer the Writer to write to in addition to the Logger
     * @return {@code this}
     */
    public IoBuilder filter(final Writer writer) {
        this.writer = writer;
        return this;
    }

    /**
     * Configures an {@link InputStream} to be wiretapped when building an InputStream. This must be set to a
     * non-{@code null} value in order to call {@link #buildInputStream()}.
     *
     * @param inputStream the InputStream to wiretap
     * @return {@code this}
     */
    public IoBuilder filter(final InputStream inputStream) {
        this.inputStream = inputStream;
        return this;
    }

    /**
     * Configures an {@link OutputStream} to be written to in addition to the underlying Logger. If no OutputStream is
     * specified, then the built OutputStream or PrintStream will only write to the underlying Logger.
     *
     * @param outputStream the OutputStream to write to in addition to the Logger
     * @return {@code this}
     */
    public IoBuilder filter(final OutputStream outputStream) {
        this.outputStream = outputStream;
        return this;
    }

    // TODO: could this builder use generics to infer the desired IO class?

    /**
     * Builds a new {@link Reader} that is wiretapped by its underlying Logger. If buffering is enabled, then a
     * {@link java.io.BufferedReader} will be returned.
     *
     * @return a new Reader wiretapped by a Logger
     * @throws IllegalStateException if no Reader was configured for this builder
     */
    public Reader buildReader() {
        final Reader in = Objects.requireNonNull(this.reader, "reader");
        if (this.buffered) {
            if (this.bufferSize > 0) {
                return new LoggerBufferedReader(in, this.bufferSize, this.logger, this.fqcn, this.level, this.marker);
            }
            return new LoggerBufferedReader(in, this.logger, this.fqcn, this.level, this.marker);
        }
        return new LoggerReader(in, this.logger, this.fqcn, this.level, this.marker);
    }

    /**
     * Builds a new {@link Writer} that is backed by a Logger and optionally writes to another Writer as well. If no
     * Writer is configured for this builder, then the returned Writer will only write to its underlying Logger.
     *
     * @return a new Writer or {@link java.io.FilterWriter} backed by a Logger
     */
    public Writer buildWriter() {
        if (this.writer == null) {
            return new LoggerWriter(this.logger, this.fqcn, this.level, this.marker);
        }
        return new LoggerFilterWriter(this.writer, this.logger, this.fqcn, this.level, this.marker);
    }

    /**
     * Builds a new {@link PrintWriter} that is backed by a Logger and optionally writes to another Writer as well. If
     * no Writer is configured for this builder, then the returned PrintWriter will only write to its underlying
     * Logger.
     *
     * @return a new PrintWriter that optionally writes to another Writer in addition to its underlying Logger
     */
    public PrintWriter buildPrintWriter() {
        if (this.writer == null) {
            return new LoggerPrintWriter(this.logger, this.autoFlush, this.fqcn, this.level, this.marker);
        }
        return new LoggerPrintWriter(this.writer, this.autoFlush, this.logger, this.fqcn, this.level, this.marker);
    }

    /**
     * Builds a new {@link InputStream} that is wiretapped by its underlying Logger. If buffering is enabled, then a
     * {@link java.io.BufferedInputStream} will be returned.
     *
     * @return a new InputStream wiretapped by a Logger
     * @throws IllegalStateException if no InputStream was configured for this builder
     */
    public InputStream buildInputStream() {
        final InputStream in = Objects.requireNonNull(this.inputStream, "inputStream");
        if (this.buffered) {
            if (this.bufferSize > 0) {
                return new LoggerBufferedInputStream(in, this.charset, this.bufferSize, this.logger, this.fqcn,
                    this.level, this.marker);
            }
            return new LoggerBufferedInputStream(in, this.charset, this.logger, this.fqcn, this.level, this.marker);
        }
        return new LoggerInputStream(in, this.charset, this.logger, this.fqcn, this.level, this.marker);
    }

    /**
     * Builds a new {@link OutputStream} that is backed by a Logger and optionally writes to another OutputStream as
     * well. If no OutputStream is configured for this builder, then the returned OutputStream will only write to its
     * underlying Logger.
     *
     * @return a new OutputStream that optionally writes to another OutputStream in addition to its underlying Logger
     */
    public OutputStream buildOutputStream() {
        if (this.outputStream == null) {
            return new LoggerOutputStream(this.logger, this.level, this.marker, this.charset, this.fqcn);
        }
        return new LoggerFilterOutputStream(this.outputStream, this.charset, this.logger, this.fqcn, this.level,
            this.marker);
    }

    /**
     * Builds a new {@link PrintStream} that is backed by a Logger and optionally writes to another OutputStream as
     * well. If no OutputStream is configured for this builder, then the returned PrintStream will only write to its
     * underlying Logger.
     *
     * @return a new PrintStream that optionally writes to another OutputStream in addition to its underlying Logger
     * @throws LoggingException if the configured character set is unsupported by {@link PrintStream}
     */
    public PrintStream buildPrintStream() {
        try {
            if (this.outputStream == null) {
                return new LoggerPrintStream(this.logger, this.autoFlush, this.charset, this.fqcn, this.level,
                    this.marker);
            }
            return new LoggerPrintStream(this.outputStream, this.autoFlush, this.charset, this.logger, this.fqcn,
                this.level, this.marker);
        } catch (final UnsupportedEncodingException e) {
            // this exception shouldn't really happen since we use Charset and not String
            throw new LoggingException(e);
        }
    }

}
