package org.gcube.keycloak.event;

import java.util.EventListener;
import java.util.HashSet;
import java.util.Set;

import org.gcube.event.publisher.AbstractEventPublisher;
import org.gcube.event.publisher.EventSender;
import org.gcube.event.publisher.HTTPWithUMAAuthEventSender;
import org.jboss.logging.Logger;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;

/**
 * @author <a href="mailto:marco.lettere@nubisware.com">Marco Lettere</a>
 * @author <a href="mailto:mauro.mugnaini@nubisware.com">Mauro Mugnaini</a>
 */
public class OrchestratorEventPublisherProvider extends AbstractEventPublisher
        implements EventListenerProvider, EventListener {

    public static final Logger logger = Logger.getLogger(OrchestratorEventPublisherProvider.class);

    private static final Set<EventType> INTERESTING_EVENTS = new HashSet<>();

    static {
        INTERESTING_EVENTS.add(EventType.CLIENT_DELETE);
        INTERESTING_EVENTS.add(EventType.CLIENT_DELETE_ERROR);
        INTERESTING_EVENTS.add(EventType.FEDERATED_IDENTITY_LINK);
        INTERESTING_EVENTS.add(EventType.FEDERATED_IDENTITY_LINK_ERROR);
        INTERESTING_EVENTS.add(EventType.IDENTITY_PROVIDER_FIRST_LOGIN);
        INTERESTING_EVENTS.add(EventType.IDENTITY_PROVIDER_FIRST_LOGIN_ERROR);
        INTERESTING_EVENTS.add(EventType.REGISTER);
        INTERESTING_EVENTS.add(EventType.REGISTER_ERROR);
        INTERESTING_EVENTS.add(EventType.UPDATE_EMAIL);
        INTERESTING_EVENTS.add(EventType.VERIFY_EMAIL_ERROR);
    }

    public OrchestratorEventPublisherProvider() {
        super();
    }

    @Override
    public void close() {
    }

    @Override
    public void onEvent(Event event) {
        if (!INTERESTING_EVENTS.contains(event.getType())) {
            logger.tracef("Skipping publish of not interesting event: %s", event.getType().toString());
            return;
        }
        logger.debug("Publishing new event to orchestrator");
        publish(KeycloakEvent.newKeycloakEvent(event));
    }

    @Override
    public void onEvent(AdminEvent event, boolean includeRepresentation) {
        if (event.getError() != null) {
            logger.debug("Skipping error admin event publish");
            return;
        }
        logger.debug("Publishing new admin event to orchestrator");
        publish(KeycloakEvent.newKeycloakAdminEvent(event, includeRepresentation));
    }

    @Override
    protected EventSender createEventSender() {
        logger.infof(
                "Creating the HTTP event sender with endpoint: %s, clientId: %s, KC token endpoint: %s, UMA adience: %s",
                OrchestratorEventPublisherProviderFactory.ORCHESTRATOR_ENDPOINT,
                OrchestratorEventPublisherProviderFactory.KEYCLOAK_CLIENT_ID,
                OrchestratorEventPublisherProviderFactory.KEYCLOAK_ENDPOINT,
                OrchestratorEventPublisherProviderFactory.ORCHESTRATOR_AUDIENCE_ID);

        return OrchestratorEventPublisherProviderFactory.KEYCLOAK_ENDPOINT != null
                ? new HTTPWithUMAAuthEventSender(
                        OrchestratorEventPublisherProviderFactory.ORCHESTRATOR_ENDPOINT,
                        OrchestratorEventPublisherProviderFactory.KEYCLOAK_CLIENT_ID,
                        OrchestratorEventPublisherProviderFactory.KEYCLOAK_CLIENT_SECRET,
                        OrchestratorEventPublisherProviderFactory.KEYCLOAK_ENDPOINT,
                        OrchestratorEventPublisherProviderFactory.ORCHESTRATOR_AUDIENCE_ID)
                : new HTTPWithUMAAuthEventSender(
                        OrchestratorEventPublisherProviderFactory.ORCHESTRATOR_ENDPOINT,
                        null, null, null, null);
    }

}
