package moe.kyokobot.bot.module.impl;

import com.mewna.catnip.Catnip;
import com.mewna.catnip.shard.event.DoubleEventType;
import com.mewna.catnip.shard.event.EventType;
import io.vertx.core.eventbus.MessageConsumer;
import moe.kyokobot.bot.module.EventManager;
import org.apache.commons.lang3.tuple.Pair;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class ModuleEventManager implements EventManager {
    private final Catnip catnip;
    private final List<MessageConsumer> consumers;

    public ModuleEventManager(Catnip catnip) {
        this.catnip = catnip;
        consumers = new ArrayList<>();
    }

    @Override
    public List<MessageConsumer> consumers() {
        return Collections.unmodifiableList(consumers);
    }

    @Override
    public <T> MessageConsumer<T> registerEventHandler(String address) {
        var listener = catnip.eventBus().<T>consumer(address);
        consumers.add(listener);
        return listener;
    }

    @Override
    public <T> MessageConsumer<T> registerEventHandler(EventType<T> eventType) {
        var listener = catnip.eventBus().<T>consumer(eventType.key());
        consumers.add(listener);
        return listener;
    }

    @Override
    public <T, U> MessageConsumer<Pair<T, U>> registerEventHandler(DoubleEventType<T, U> eventType) {
        var listener = catnip.eventBus().<Pair<T, U>>consumer(eventType.key());
        consumers.add(listener);
        return listener;
    }

    @Override
    public <T> MessageConsumer<T> registerEventHandler(String address, Consumer<T> handler) {
        var listener = catnip.eventBus().<T>consumer(address, m -> handler.accept(m.body()));
        consumers.add(listener);
        return listener;
    }

    @Override
    public <T> MessageConsumer<T> registerEventHandler(EventType<T> eventType, Consumer<T> handler) {
        var listener = catnip.eventBus().<T>consumer(eventType.key(), m -> handler.accept(m.body()));
        consumers.add(listener);
        return listener;
    }

    @Override
    public <T, U> MessageConsumer<Pair<T, U>> registerEventHandler(DoubleEventType<T, U> eventType,
                                                                   BiConsumer<T, U> handler) {
        var listener = catnip.eventBus().<Pair<T, U>>consumer(eventType.key(),
                m -> handler.accept(m.body().getLeft(), m.body().getRight()));
        consumers.add(listener);
        return listener;
    }

    @Override
    public void unregisterEventHandler(MessageConsumer listener) {
        listener.unregister();
        consumers.remove(listener);
    }

    @Override
    public void shutdown() {
        consumers.forEach(MessageConsumer::unregister);
        consumers.clear();
    }
}