package com.atlassian.stash.internal.event;

import java.util.Date;

/**
 * Provides statistics about the event subsystem for JMX
 *
 * @since 4.8
 */
@SuppressWarnings("unused")
public class EventStatisticsMXBean {

    private final TransactionAwareEventPublisher eventPublisher;
    private final EventThreadPoolExecutor eventThreadPoolExecutor;
    private final AsyncBatchingInvokersTransformer invokersTransformer;
    private final int queueCapacity;

    public EventStatisticsMXBean(TransactionAwareEventPublisher eventPublisher,
                                 EventThreadPoolExecutor eventThreadPoolExecutor,
                                 AsyncBatchingInvokersTransformer invokersTransformer,
                                 int queueCapacity) {
        this.eventPublisher = eventPublisher;
        this.eventThreadPoolExecutor = eventThreadPoolExecutor;
        this.invokersTransformer = invokersTransformer;
        this.queueCapacity = queueCapacity;
    }

    /**
     * @return the total number of listener callbacks that have been performed. An event that is delivered to 10
     *         listeners counts as 10 dispatches.
     */
    public long getDispatchedCount() {
        // Note: we're not using eventThreadPoolExecutor.getCompletedTaskCount because that would under-report the
        // counts. Only @AsynchronousEvents are dispatched using the executor and even these are transformed in
        // batches of log2(listenerCount) to reduce the pressure on the event queue.
        return invokersTransformer.getDispatchedCount();
    }

    /**
     * @return the date of the last event being rejected, or {@code null} if no event has been rejected
     */
    public Date getLastRejection() {
        return eventThreadPoolExecutor.getLastRejectionDate();
    }

    /**
     * @return the total number of events delivered. An event that is delivered to 10 listeners counts a 1 event.
     */
    public long getPublishedCount() {
        return eventPublisher.getPublishedEventCount();
    }

    /**
     * @return the maximum number of event callbacks that can be queued before events are rejected
     */
    public int getQueueCapacity() {
        return queueCapacity;
    }

    /**
     * @return the number of event callbacks that have been queued but haven't been dispatched yet.
     */
    public long getQueueLength() {
        return eventThreadPoolExecutor.getQueue().size();
    }

    /**
     * @return the total number of events that were not dispatched because the event queue was full
     */
    public long getRejectedCount() {
        return eventThreadPoolExecutor.getRejectionCount();
    }

    /**
     * @return the remaining number of event callbacks that can be queued before events are rejected
     */
    public int getRemainingQueueCapacity() {
        return eventThreadPoolExecutor.getQueue().remainingCapacity();
    }
}
