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

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;
import de.accso.flexinale.common.api.event.EventContext;
import de.accso.flexinale.ticketing.api_contract.event.TicketGekauftEvent;
import de.accso.flexinale.ticketing.api_contract.event.TicketUngueltigEvent;
import de.accso.flexinale.ticketing.api_contract.event.model.TicketTO;
import de.accso.flexinale.ticketing.api_out.event.mapper.Ticket2TicketTOMapper;
import de.accso.flexinale.ticketing.application.services.TicketPublication;
import de.accso.flexinale.ticketing.domain.model.Ticket;

import java.util.List;

public class TicketPublisher implements EventPublisher.EventPublisher2<TicketGekauftEvent, TicketUngueltigEvent>, TicketPublication {
    private final EventBus<TicketGekauftEvent> ticketGekauftEventEventBus;
    private final EventBus<TicketUngueltigEvent> ticketUngueltigEventEventBus;

    private final EventNotification notification;

    public TicketPublisher(final EventBusFactory eventBusFactory,
                           final EventNotification notification) {
        this.ticketGekauftEventEventBus = eventBusFactory.createOrGetEventBusFor(TicketGekauftEvent.class);
        this.ticketUngueltigEventEventBus = eventBusFactory.createOrGetEventBusFor(TicketUngueltigEvent.class);

        this.notification = notification;
    }

    @Override
    public void publishGekaufteTickets(final List<Ticket> tickets) {
        EventContext predecessorEventContext = ticketGekauftEventEventBus.getEventContextHolder().get();

        tickets.forEach(ticket -> {
            TicketTO mappedTicket = Ticket2TicketTOMapper.map(ticket);
            post(TicketGekauftEvent.class,
                    (predecessorEventContext == null) ? new TicketGekauftEvent(mappedTicket)
                                                      : new TicketGekauftEvent(predecessorEventContext, mappedTicket));
        });
    }

    @Override
    public void publishUngueltigeTickets(final List<Ticket> tickets) {
        EventContext predecessorEventContext = ticketUngueltigEventEventBus.getEventContextHolder().get();

        tickets.forEach(ticket -> {
            TicketTO mappedTicket = Ticket2TicketTOMapper.map(ticket);
            post2(TicketUngueltigEvent.class,
                    (predecessorEventContext == null) ? new TicketUngueltigEvent(mappedTicket)
                                                      : new TicketUngueltigEvent(predecessorEventContext, mappedTicket));
        });
    }

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

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

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