// Path: app/src/main/java/ultimategdbot/database/GuildConfig.java
// @Value.Immutable
// @Criteria
// @Criteria.Repository(facets = { ReactorReadable.class, ReactorWritable.class })
// @JsonSerialize(as = ImmutableGuildConfig.class)
// @JsonDeserialize(as = ImmutableGuildConfig.class)
// public interface GuildConfig {
// 
//     @Criteria.Id
//     @JsonProperty("_id")
//     long guildId();
// 
//     Optional<String> prefix();
// 
//     Optional<String> locale();
// }
// 
// Path: app/src/main/java/ultimategdbot/service/DatabaseService.java
// @RdiService
// public final class DatabaseService {
// 
//     private final Backend backend;
// 
//     @RdiFactory
//     public DatabaseService(ConfigContainer configContainer) {
//         final var config = configContainer.get(MongoDBConfig.class);
//         final var mapper = new ObjectMapper()
//                 .registerModule(new BsonModule())
//                 .registerModule(new Jdk8Module())
//                 .registerModule(new IdAnnotationModule())
//                 .addHandler(new UnknownPropertyHandler(true));
//         @SuppressWarnings("UnstableApiUsage")
//         final var registry = JacksonCodecs.registryFromMapper(mapper);
//         final var client = MongoClients.create(config.connectionString());
//         final var db = client.getDatabase(config.databaseName()).withCodecRegistry(registry);
//         this.backend = new MongoBackend(MongoSetup.of(db));
//     }
// 
//     public GuildConfigDao guildConfigDao() {
//         return new GuildConfigDao(backend);
//     }
// 
//     public BlacklistDao blacklistDao() {
//         return new BlacklistDao(backend);
//     }
// 
//     public BotAdminDao botAdminDao() {
//         return new BotAdminDao(backend);
//     }
// 
//     public GdLinkedUserDao gdLinkedUserDao() {
//         return new GdLinkedUserDao(backend);
//     }
// 
//     public GdLeaderboardDao gdLeaderboardDao() {
//         return new GdLeaderboardDao(backend);
//     }
// 
//     public GdLeaderboardBanDao gdLeaderboardBanDao() {
//         return new GdLeaderboardBanDao(backend);
//     }
// 
//     public GdModDao gdModDao() {
//         return new GdModDao(backend);
//     }
// 
//     public GdAwardedLevelDao gdAwardedLevelDao() {
//         return new GdAwardedLevelDao(backend);
//     }
// }


import botrino.interaction.InteractionEventProcessor;
import com.github.alex1304.rdi.finder.annotation.RdiFactory;
import com.github.alex1304.rdi.finder.annotation.RdiService;
import discord4j.common.util.Snowflake;
import discord4j.core.event.domain.interaction.InteractionCreateEvent;
import reactor.core.publisher.Mono;
import reactor.function.TupleUtils;
import reactor.util.annotation.Nullable;
import ultimategdbot.database.GuildConfig;
import ultimategdbot.database.ImmutableGuildConfig;
import ultimategdbot.service.DatabaseService;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
    private UGDBEventProcessor(DatabaseService db, Map<Long, GuildConfig> guildConfigCache,
                               Set<Long> blacklistCache) {
        this.db = db;
        this.guildConfigCache = guildConfigCache;
        this.blacklistCache = blacklistCache;
    }

    @RdiFactory
    public static Mono<UGDBEventProcessor> create(DatabaseService db) {
        return Mono.zip(
                    db.guildConfigDao().getAll().collect(Collectors.toMap(GuildConfig::guildId, Function.identity())),
                    db.blacklistDao().getAllIds().collect(Collectors.toSet()))
                .map(TupleUtils.function((guildConfigCache, blacklistCache) ->
                        new UGDBEventProcessor(db, new ConcurrentHashMap<>(guildConfigCache),
                                Collections.synchronizedSet(new HashSet<>(blacklistCache)))));
    }

    @Override
    public Mono<Boolean> filter(InteractionCreateEvent event) {
        var guildId = event.getInteraction().getGuildId().map(Snowflake::asLong).orElse(null);
        var authorId = event.getInteraction().getUser().getId().asLong();
        var channelId = event.getInteraction().getChannelId().asLong();
        return Mono.just((guildId == null || !blacklistCache.contains(guildId))
                        && !blacklistCache.contains(authorId)
                        && !blacklistCache.contains(channelId));
    }

    @Override
    public Mono<Locale> computeLocale(InteractionCreateEvent event) {
        return Mono.justOrEmpty(event.getInteraction().getGuildId().map(Snowflake::asLong))
// Path: app/src/main/java/ultimategdbot/database/GuildConfig.java
// @Value.Immutable
// @Criteria
// @Criteria.Repository(facets = { ReactorReadable.class, ReactorWritable.class })
// @JsonSerialize(as = ImmutableGuildConfig.class)
// @JsonDeserialize(as = ImmutableGuildConfig.class)
// public interface GuildConfig {
// 
//     @Criteria.Id
//     @JsonProperty("_id")
//     long guildId();
// 
//     Optional<String> prefix();
// 
//     Optional<String> locale();
// }
// 
// Path: app/src/main/java/ultimategdbot/service/DatabaseService.java
// @RdiService
// public final class DatabaseService {
// 
//     private final Backend backend;
// 
//     @RdiFactory
//     public DatabaseService(ConfigContainer configContainer) {
//         final var config = configContainer.get(MongoDBConfig.class);
//         final var mapper = new ObjectMapper()
//                 .registerModule(new BsonModule())
//                 .registerModule(new Jdk8Module())
//                 .registerModule(new IdAnnotationModule())
//                 .addHandler(new UnknownPropertyHandler(true));
//         @SuppressWarnings("UnstableApiUsage")
//         final var registry = JacksonCodecs.registryFromMapper(mapper);
//         final var client = MongoClients.create(config.connectionString());
//         final var db = client.getDatabase(config.databaseName()).withCodecRegistry(registry);
//         this.backend = new MongoBackend(MongoSetup.of(db));
//     }
// 
//     public GuildConfigDao guildConfigDao() {
//         return new GuildConfigDao(backend);
//     }
// 
//     public BlacklistDao blacklistDao() {
//         return new BlacklistDao(backend);
//     }
// 
//     public BotAdminDao botAdminDao() {
//         return new BotAdminDao(backend);
//     }
// 
//     public GdLinkedUserDao gdLinkedUserDao() {
//         return new GdLinkedUserDao(backend);
//     }
// 
//     public GdLeaderboardDao gdLeaderboardDao() {
//         return new GdLeaderboardDao(backend);
//     }
// 
//     public GdLeaderboardBanDao gdLeaderboardBanDao() {
//         return new GdLeaderboardBanDao(backend);
//     }
// 
//     public GdModDao gdModDao() {
//         return new GdModDao(backend);
//     }
// 
//     public GdAwardedLevelDao gdAwardedLevelDao() {
//         return new GdAwardedLevelDao(backend);
//     }
// }


// Path: app/src/main/java/ultimategdbot/framework/UGDBEventProcessor.java
import botrino.interaction.InteractionEventProcessor;
import com.github.alex1304.rdi.finder.annotation.RdiFactory;
import com.github.alex1304.rdi.finder.annotation.RdiService;
import discord4j.common.util.Snowflake;
import discord4j.core.event.domain.interaction.InteractionCreateEvent;
import reactor.core.publisher.Mono;
import reactor.function.TupleUtils;
import reactor.util.annotation.Nullable;
import ultimategdbot.database.GuildConfig;
import ultimategdbot.database.ImmutableGuildConfig;
import ultimategdbot.service.DatabaseService;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

    private UGDBEventProcessor(DatabaseService db, Map<Long, GuildConfig> guildConfigCache,
                               Set<Long> blacklistCache) {
        this.db = db;
        this.guildConfigCache = guildConfigCache;
        this.blacklistCache = blacklistCache;
    }

    @RdiFactory
    public static Mono<UGDBEventProcessor> create(DatabaseService db) {
        return Mono.zip(
                    db.guildConfigDao().getAll().collect(Collectors.toMap(GuildConfig::guildId, Function.identity())),
                    db.blacklistDao().getAllIds().collect(Collectors.toSet()))
                .map(TupleUtils.function((guildConfigCache, blacklistCache) ->
                        new UGDBEventProcessor(db, new ConcurrentHashMap<>(guildConfigCache),
                                Collections.synchronizedSet(new HashSet<>(blacklistCache)))));
    }

    @Override
    public Mono<Boolean> filter(InteractionCreateEvent event) {
        var guildId = event.getInteraction().getGuildId().map(Snowflake::asLong).orElse(null);
        var authorId = event.getInteraction().getUser().getId().asLong();
        var channelId = event.getInteraction().getChannelId().asLong();
        return Mono.just((guildId == null || !blacklistCache.contains(guildId))
                        && !blacklistCache.contains(authorId)
                        && !blacklistCache.contains(channelId));
    }

    @Override
    public Mono<Locale> computeLocale(InteractionCreateEvent event) {
        return Mono.justOrEmpty(event.getInteraction().getGuildId().map(Snowflake::asLong))
                .flatMap(guildId -> Mono.justOrEmpty(guildConfigCache.get(guildId)))