/*
 * 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.juli;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.LogRecord;

/**
 * A {@link FileHandler} implementation that uses a queue of log entries.
 * <p>
 * Configuration properties are inherited from the {@link FileHandler} class. This class does not add its own
 * configuration properties for the logging configuration, but relies on the following system properties instead:
 * </p>
 * <ul>
 * <li><code>org.apache.juli.AsyncOverflowDropType</code> Default value: <code>1</code></li>
 * <li><code>org.apache.juli.AsyncMaxRecordCount</code> Default value: <code>10000</code></li>
 * </ul>
 * <p>
 * See the System Properties page in the configuration reference of Tomcat.
 * </p>
 */
public class AsyncFileHandler extends FileHandler {

    static final String THREAD_PREFIX = "AsyncFileHandlerWriter-";

    /**
     * Overflow policy: drop the last record in the queue.
     */
    public static final int OVERFLOW_DROP_LAST = 1;

    /**
     * Overflow policy: drop the first (oldest) record in the queue.
     */
    public static final int OVERFLOW_DROP_FIRST = 2;

    /**
     * Overflow policy: flush the queue and retry.
     */
    public static final int OVERFLOW_DROP_FLUSH = 3;

    /**
     * Overflow policy: drop the current record.
     */
    public static final int OVERFLOW_DROP_CURRENT = 4;

    /**
     * Default overflow drop type value.
     */
    public static final int DEFAULT_OVERFLOW_DROP_TYPE = 1;

    /**
     * Default maximum number of records in the queue.
     */
    public static final int DEFAULT_MAX_RECORDS = 10000;

    /**
     * Configured overflow drop type from system property.
     */
    public static final int OVERFLOW_DROP_TYPE = Integer.parseInt(
            System.getProperty("org.apache.juli.AsyncOverflowDropType", Integer.toString(DEFAULT_OVERFLOW_DROP_TYPE)));

    /**
     * Configured maximum record count from system property.
     */
    public static final int MAX_RECORDS = Integer
            .parseInt(System.getProperty("org.apache.juli.AsyncMaxRecordCount", Integer.toString(DEFAULT_MAX_RECORDS)));

    private static final LoggerExecutorService LOGGER_SERVICE =
            new LoggerExecutorService(OVERFLOW_DROP_TYPE, MAX_RECORDS);

    private final Object closeLock = new Object();
    /**
     * Indicates whether this handler has been closed.
     */
    protected volatile boolean closed = false;
    private final LoggerExecutorService loggerService;

    /**
     * Constructs an AsyncFileHandler with default settings.
     */
    public AsyncFileHandler() {
        this(null, null, null);
    }

    /**
     * Constructs an AsyncFileHandler with the specified directory, prefix, and suffix.
     *
     * @param directory The directory for log files
     * @param prefix The log file name prefix
     * @param suffix The log file name suffix
     */
    public AsyncFileHandler(String directory, String prefix, String suffix) {
        this(directory, prefix, suffix, null);
    }

    /**
     * Constructs an AsyncFileHandler with the specified directory, prefix, suffix, and max days.
     *
     * @param directory The directory for log files
     * @param prefix The log file name prefix
     * @param suffix The log file name suffix
     * @param maxDays Maximum number of days to keep log files
     */
    public AsyncFileHandler(String directory, String prefix, String suffix, Integer maxDays) {
        this(directory, prefix, suffix, maxDays, LOGGER_SERVICE);
    }

    AsyncFileHandler(String directory, String prefix, String suffix, Integer maxDays,
            LoggerExecutorService loggerService) {
        super(directory, prefix, suffix, maxDays);
        loggerService.registerHandler();
        this.loggerService = loggerService;
    }

    @Override
    public void close() {
        if (closed) {
            return;
        }
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }
        loggerService.deregisterHandler();
        super.close();
    }

    @Override
    public void open() {
        if (!closed) {
            return;
        }
        synchronized (closeLock) {
            if (!closed) {
                return;
            }
            closed = false;
        }
        loggerService.registerHandler();
        super.open();
    }

    @Override
    public void publish(LogRecord record) {
        if (!isLoggable(record)) {
            return;
        }
        // fill source entries, before we hand the record over to another
        // thread with another class loader
        record.getSourceMethodName();
        loggerService.execute(() -> {
            /*
             * During Tomcat shutdown, the Handlers are closed before the executor queue is flushed therefore the closed
             * flag is ignored if the executor is shutting down.
             */
            if (!closed || loggerService.isTerminating()) {
                publishInternal(record);
            }
        });
    }

    /**
     * Publishes a log record to the underlying handler.
     *
     * @param record The log record to publish
     */
    protected void publishInternal(LogRecord record) {
        super.publish(record);
    }


    static class LoggerExecutorService extends ThreadPoolExecutor {

        private static final ThreadFactory THREAD_FACTORY = new ThreadFactory(THREAD_PREFIX);

        /*
         * Implementation note: Use of this count could be extended to start/stop the LoggerExecutorService but that
         * would require careful locking as the current size of the queue also needs to be taken into account and there
         * are lost of edge cases when rapidly starting and stopping handlers.
         */
        private final AtomicInteger handlerCount = new AtomicInteger();

        LoggerExecutorService(final int overflowDropType, final int maxRecords) {
            super(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(maxRecords), THREAD_FACTORY);
            switch (overflowDropType) {
                case OVERFLOW_DROP_FIRST -> setRejectedExecutionHandler(new DiscardOldestPolicy());
                case OVERFLOW_DROP_FLUSH -> setRejectedExecutionHandler(new DropFlushPolicy());
                case OVERFLOW_DROP_CURRENT -> setRejectedExecutionHandler(new DiscardPolicy());
                default -> setRejectedExecutionHandler(new DropLastPolicy());
            }
        }

        @Override
        public LinkedBlockingDeque<Runnable> getQueue() {
            return (LinkedBlockingDeque<Runnable>) super.getQueue();
        }

        public void registerHandler() {
            handlerCount.incrementAndGet();
        }

        public void deregisterHandler() {
            int newCount = handlerCount.decrementAndGet();
            if (newCount == 0) {
                try {
                    Thread dummyHook = new Thread();
                    Runtime.getRuntime().addShutdownHook(dummyHook);
                    Runtime.getRuntime().removeShutdownHook(dummyHook);
                } catch (IllegalStateException ise) {
                    // JVM is shutting down.
                    // Allow up to 10s for the queue to be emptied
                    shutdown();
                    try {
                        awaitTermination(10, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                    shutdownNow();
                }
            }
        }
    }


    private static class DropFlushPolicy implements RejectedExecutionHandler {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            while (true) {
                if (executor.isShutdown()) {
                    break;
                }
                try {
                    if (executor.getQueue().offer(r, 1000, TimeUnit.MILLISECONDS)) {
                        break;
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RejectedExecutionException("Interrupted", e);
                }
            }
        }
    }

    private static class DropLastPolicy implements RejectedExecutionHandler {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            if (!executor.isShutdown()) {
                ((LoggerExecutorService) executor).getQueue().pollLast();
                executor.execute(r);
            }
        }
    }
}
