/*
 * 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.core.appender.db;

import java.io.Flushable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractManager;
import org.apache.logging.log4j.core.appender.ManagerFactory;

/**
 * Manager that allows database appenders to have their configuration reloaded without losing events.
 */
public abstract class AbstractDatabaseManager extends AbstractManager implements Flushable {
    
    /**
     * Implementations should extend this class for passing data between the getManager method and the manager factory
     * class.
     */
    protected abstract static class AbstractFactoryData {
        private final int bufferSize;
        private final Layout<? extends Serializable> layout;

        /**
         * Constructs the base factory data.
         *
         * @param bufferSize The size of the buffer.
         * @param layout The appender-level layout
         */
        protected AbstractFactoryData(final int bufferSize, final Layout<? extends Serializable> layout) {
            this.bufferSize = bufferSize;
            this.layout = layout;
        }

        /**
         * Gets the buffer size.
         *
         * @return the buffer size.
         */
        public int getBufferSize() {
            return bufferSize;
        }

        /**
         * Gets the layout.
         * 
         * @return the layout.
         */
        public Layout<? extends Serializable> getLayout() {
            return layout;
        }
    }

    /**
     * Implementations should define their own getManager method and call this method from that to create or get
     * existing managers.
     *
     * @param name The manager name, which should include any configuration details that one might want to be able to
     *             reconfigure at runtime, such as database name, username, (hashed) password, etc.
     * @param data The concrete instance of {@link AbstractFactoryData} appropriate for the given manager.
     * @param factory A factory instance for creating the appropriate manager.
     * @param <M> The concrete manager type.
     * @param <T> The concrete {@link AbstractFactoryData} type.
     * @return a new or existing manager of the specified type and name.
     */
    protected static <M extends AbstractDatabaseManager, T extends AbstractFactoryData> M getManager(
            final String name, final T data, final ManagerFactory<M, T> factory
    ) {
        return AbstractManager.getManager(name, factory, data);
    }

    private final ArrayList<LogEvent> buffer;

    private final int bufferSize;
    private final Layout<? extends Serializable> layout;
    private boolean running;
    /**
     * Instantiates the base manager.
     *
     * @param name The manager name, which should include any configuration details that one might want to be able to
     *             reconfigure at runtime, such as database name, username, (hashed) password, etc.
     * @param bufferSize The size of the log event buffer.
     */
    protected AbstractDatabaseManager(final String name, final int bufferSize) {
        this(name, bufferSize, null);
    }

    /**
     * Instantiates the base manager.
     *
     * @param name The manager name, which should include any configuration details that one might want to be able to
     *             reconfigure at runtime, such as database name, username, (hashed) password, etc.
     * @param layout the Appender-level layout.
     * @param bufferSize The size of the log event buffer.
     */
    protected AbstractDatabaseManager(final String name, final int bufferSize, final Layout<? extends Serializable> layout) {
        super(null, name);
        this.bufferSize = bufferSize;
        this.buffer = new ArrayList<>(bufferSize + 1);
        this.layout = layout;
    }

    protected void buffer(final LogEvent event) {
        this.buffer.add(event.toImmutable());
        if (this.buffer.size() >= this.bufferSize || event.isEndOfBatch()) {
            this.flush();
        }
    }

    /**
     * Commits any active transaction (if applicable) and disconnects from the database (returns the connection to the
     * connection pool). With buffering enabled, this is called when flushing the buffer completes, after the last call
     * to {@link #writeInternal}. With buffering disabled, this is called immediately after every invocation of
     * {@link #writeInternal}.
     * @return true if all resources were closed normally, false otherwise.
     */
    protected abstract boolean commitAndClose();

    /**
     * Connects to the database and starts a transaction (if applicable). With buffering enabled, this is called when
     * flushing the buffer begins, before the first call to {@link #writeInternal}. With buffering disabled, this is
     * called immediately before every invocation of {@link #writeInternal}.
     */
    protected abstract void connectAndStart();

    /**
     * This method is called automatically when the buffer size reaches its maximum or at the beginning of a call to
     * {@link #shutdown()}. It can also be called manually to flush events to the database.
     */
    @Override
    public final synchronized void flush() {
        if (this.isRunning() && isBuffered()) {
            this.connectAndStart();
            try {
                for (final LogEvent event : this.buffer) {
                    this.writeInternal(event, layout != null ? layout.toSerializable(event) : null);
                }
            } finally {
                this.commitAndClose();
                // not sure if this should be done when writing the events failed
                this.buffer.clear();
            }
        }
    }

    protected boolean isBuffered() {
        return this.bufferSize > 0;
    }

    /**
     * Indicates whether the manager is currently connected {@link #startup()} has been called and {@link #shutdown()}
     * has not been called).
     *
     * @return {@code true} if the manager is connected.
     */
    public final boolean isRunning() {
        return this.running;
    }

    @Override
    public final boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
        return this.shutdown();
    }

    /**
     * This method is called from the {@link #close()} method when the appender is stopped or the appender's manager
     * is replaced. If it has not already been called, it calls {@link #shutdownInternal()} and catches any exceptions
     * it might throw.
     * @return true if all resources were closed normally, false otherwise.
     */
    public final synchronized boolean shutdown() {
        boolean closed = true;
        this.flush();
        if (this.isRunning()) {
            try {
                closed &= this.shutdownInternal();
            } catch (final Exception e) {
                logWarn("Caught exception while performing database shutdown operations", e);
                closed = false;
            } finally {
                this.running = false;
            }
        }
        return closed;
    }

    /**
     * Implementations should implement this method to perform any proprietary disconnection / shutdown operations. This
     * method will never be called twice on the same instance, and it will only be called <em>after</em>
     * {@link #startupInternal()}. It is safe to throw any exceptions from this method. This method does not
     * necessarily disconnect from the database for the same reasons outlined in {@link #startupInternal()}.
     * @return true if all resources were closed normally, false otherwise.
     */
    protected abstract boolean shutdownInternal() throws Exception;

    /**
     * This method is called within the appender when the appender is started. If it has not already been called, it
     * calls {@link #startupInternal()} and catches any exceptions it might throw.
     */
    public final synchronized void startup() {
        if (!this.isRunning()) {
            try {
                this.startupInternal();
                this.running = true;
            } catch (final Exception e) {
                logError("Could not perform database startup operations", e);
            }
        }
    }

    /**
     * Implementations should implement this method to perform any proprietary startup operations. This method will
     * never be called twice on the same instance. It is safe to throw any exceptions from this method. This method
     * does not necessarily connect to the database, as it is generally unreliable to connect once and use the same
     * connection for hours.
     */
    protected abstract void startupInternal() throws Exception;

    @Override
    public final String toString() {
        return this.getName();
    }

    /**
     * This method manages buffering and writing of events.
     *
     * @param event The event to write to the database.
     * @param serializable Serializable event
     */
    public final synchronized void write(final LogEvent event, final Serializable serializable) {
        if (isBuffered()) {
            buffer(event);
        } else {
            writeThrough(event, serializable);
        }
    }

    /**
     * Performs the actual writing of the event in an implementation-specific way. This method is called immediately
     * from {@link #write(LogEvent, Serializable)} if buffering is off, or from {@link #flush()} if the buffer has reached its limit.
     *
     * @param event The event to write to the database.
     */
    protected abstract void writeInternal(LogEvent event, Serializable serializable);

    protected void writeThrough(final LogEvent event, final Serializable serializable) {
        this.connectAndStart();
        try {
            this.writeInternal(event, serializable);
        } finally {
            this.commitAndClose();
        }
    }
}
