package com.atlassian.stash.internal.server.analytics;

import com.atlassian.analytics.api.events.MauEvent;
import com.atlassian.bitbucket.event.request.RequestEndedEvent;
import com.atlassian.bitbucket.experimental.request.ExperimentalRequestContext;
import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

import static java.util.Optional.ofNullable;

/**
 * @since 4.1
 */
@Component
public class MauEventPublisher {

    private final EventPublisher eventPublisher;
    private final long eventPublishInterval;
    private final ConcurrentMap<String, Long> lastSentCache;

    @Autowired
    public MauEventPublisher(EventPublisher eventPublisher,
                             @Value("${analytics.mauevent.publish.interval}") int eventPublishIntervalInMinutes) {
        this(eventPublisher, eventPublishIntervalInMinutes, new ConcurrentHashMap<>());
    }

    @VisibleForTesting
    MauEventPublisher(EventPublisher eventPublisher,
                      @Value("${analytics.mauevent.publish.interval}") int eventPublishIntervalInMinutes,
                      ConcurrentMap lastSentCache) {
        this.eventPublisher = eventPublisher;
        this.eventPublishInterval = TimeUnit.MINUTES.toMillis(eventPublishIntervalInMinutes);
        this.lastSentCache = lastSentCache;
    }

    @EventListener
    public void onRequestEnded(RequestEndedEvent event) {
        ExperimentalRequestContext requestContext = (ExperimentalRequestContext) event.getRequestContext();
        requestContext.getAuthenticatedUser().ifPresent(user -> {
            String emailAddress = user.getEmailAddress();
            if (StringUtils.isNotBlank(emailAddress)) {
                Long lastSentTime = ofNullable(lastSentCache.get(emailAddress)).orElse(0L);
                long currentTime = System.currentTimeMillis();

                if (currentTime > lastSentTime + eventPublishInterval) {
                    eventPublisher.publish(MauEvent.withEmail(emailAddress));
                    lastSentCache.put(emailAddress, currentTime);
                }
            }
        });
    }
}
