package de.accso.flexinale.backoffice.api_out.event;

import de.accso.flexinale.backoffice.api_contract.event.VorfuehrungCRUDEvent;
import de.accso.flexinale.backoffice.api_contract.event.VorfuehrungCreatedEvent;
import de.accso.flexinale.backoffice.api_contract.event.VorfuehrungDeletedEvent;
import de.accso.flexinale.backoffice.api_contract.event.VorfuehrungUpdatedEvent;
import de.accso.flexinale.backoffice.api_contract.event.model.VorfuehrungTO;
import de.accso.flexinale.backoffice.api_out.event.mapper.Vorfuehrung2VorfuehrungTOMapper;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.api.eventbus.EventBus;
import de.accso.flexinale.common.api.eventbus.EventBusFactory;
import de.accso.flexinale.common.api.eventbus.EventNotification;
import de.accso.flexinale.common.api.eventbus.EventPublisher.EventPublisher3;

import java.util.Collection;

@SuppressWarnings("unused")
public class VorfuehrungPublisher implements EventPublisher3<VorfuehrungCreatedEvent, VorfuehrungUpdatedEvent, VorfuehrungDeletedEvent> {
    private final EventBus<VorfuehrungCreatedEvent> createBus;
    private final EventBus<VorfuehrungUpdatedEvent> updateBus;
    private final EventBus<VorfuehrungDeletedEvent> deleteBus;

    private final EventNotification notification;

    public VorfuehrungPublisher(final EventBusFactory eventBusFactory,
                                final EventNotification notification) {
        this.createBus = eventBusFactory.createOrGetEventBusFor(VorfuehrungCreatedEvent.class);
        this.updateBus = eventBusFactory.createOrGetEventBusFor(VorfuehrungUpdatedEvent.class);
        this.deleteBus = eventBusFactory.createOrGetEventBusFor(VorfuehrungDeletedEvent.class);

        this.notification = notification;
    }

    public void publishNewVorfuehrungen(final Collection<Vorfuehrung> vorfuehrungen) {
        publishCRUDEvents(vorfuehrungen, VorfuehrungCRUDEvent.CRUD.CREATE);
    }

    public void publishUpdatedVorfuehrungen(final Collection<Vorfuehrung> vorfuehrungen) {
        publishCRUDEvents(vorfuehrungen, VorfuehrungCRUDEvent.CRUD.UPDATE);
    }

    // currently we do not publish Deletions events
    public void publishDeletedVorfuehrungen(final Collection<Vorfuehrung> vorfuehrungen) {
        publishCRUDEvents(vorfuehrungen, VorfuehrungCRUDEvent.CRUD.DELETE);
    }

    private void publishCRUDEvents(final Collection<Vorfuehrung> changedVorfuehrungen, final VorfuehrungCRUDEvent.CRUD mode) {
        for (Vorfuehrung vorfuehrung: changedVorfuehrungen) {
            VorfuehrungTO vorfuehrungTO = Vorfuehrung2VorfuehrungTOMapper.map(vorfuehrung);
            switch (mode) {
                case CREATE -> this.post (VorfuehrungCreatedEvent.class, new VorfuehrungCreatedEvent(vorfuehrungTO));
                case UPDATE -> this.post2(VorfuehrungUpdatedEvent.class, new VorfuehrungUpdatedEvent(vorfuehrungTO));
                case DELETE -> this.post3(VorfuehrungDeletedEvent.class, new VorfuehrungDeletedEvent(vorfuehrungTO));
            }
        }
    }

    @Override
    public String getName() {
        return VorfuehrungPublisher.class.getName();
    }

    @Override
    public void post(final Class<VorfuehrungCreatedEvent> eventType, final VorfuehrungCreatedEvent event) {
        this.createBus.publish(eventType, event);
        this.notification.notify(event);
    }

    @Override
    public void post2(final Class<VorfuehrungUpdatedEvent> eventType, final VorfuehrungUpdatedEvent event) {
        this.updateBus.publish(eventType, event);
        this.notification.notify(event);
    }

    @Override
    public void post3(final Class<VorfuehrungDeletedEvent> eventType, final VorfuehrungDeletedEvent event) {
        this.deleteBus.publish(eventType, event);
        this.notification.notify(event);
    }
}
