package com.feed_the_beast.ftbcurseappbot.persistence;

import com.beust.jcommander.internal.Maps;
import com.feed_the_beast.ftbcurseappbot.Main;
import com.feed_the_beast.ftbcurseappbot.persistence.data.MongoCommand;
import com.feed_the_beast.javacurselib.service.contacts.contacts.ContactsResponse;
import com.feed_the_beast.javacurselib.service.contacts.contacts.GroupNotification;
import com.feed_the_beast.javacurselib.service.groups.servers.GroupRoleDetails;
import com.feed_the_beast.javacurselib.utils.CurseGUID;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * basic service for caching data.
 */
@Slf4j
public class CacheService {
    private LoadingCache<CurseGUID, List<GroupRoleDetails>> grouproledetails;
    private LoadingCache<CurseGUID, GroupNotification> groupnotifications;
    @Getter
    private Map<CurseGUID, List<MongoCommand>> customServerCommands;
    @Getter
    private Supplier<ContactsResponse> contacts = Suppliers.memoizeWithExpiration(this::getContactsFromURL,
            5, TimeUnit.MINUTES);

    public CacheService () {
        customServerCommands = Maps.newHashMap();
        grouproledetails = CacheBuilder.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .build(new CacheLoader<CurseGUID, List<GroupRoleDetails>>() { // build the cacheloader

                    @Override
                    public List<GroupRoleDetails> load (CurseGUID serverId) throws Exception {
                        List<GroupRoleDetails> server = null;
                        try {
                            server = Main.getRestUserEndpoints().servers.getServerRoles(serverId).get();
                        } catch (InterruptedException | ExecutionException e) {
                            log.error("error getting server roles from curse for server: " + serverId, e);
                        }
                        return server;
                    }
                });
        groupnotifications = CacheBuilder.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .build(new CacheLoader<CurseGUID, GroupNotification>() { // build the cacheloader

                    @Override
                    public GroupNotification load (CurseGUID serverId) throws Exception {
                        GroupNotification server = null;
                        try {
                            server = Main.getRestUserEndpoints().groups.get(serverId, false).get();
                        } catch (InterruptedException | ExecutionException e) {
                            log.error("error getting groupNotification from curse for server: " + serverId, e);
                        }
                        return server;
                    }
                });

    }

    @Nonnull
    public Optional<List<MongoCommand>> getCustomCommandsForServer(@Nonnull CurseGUID serverId) {
        return Optional.ofNullable(customServerCommands.get(serverId));
    }
    public void setServerCommandsEntry (@Nonnull CurseGUID serverId, List<MongoCommand> commands) {
            customServerCommands.put(serverId, commands);
    }

    @Nonnull
    public Optional<List<GroupRoleDetails>> getServerRole (@Nonnull CurseGUID serverId) {
        try {
            return Optional.of(grouproledetails.get(serverId));
        } catch (ExecutionException e) {
            log.error("error getting details from cache", e);
        }
        return Optional.empty();
    }

    @Nullable
    private ContactsResponse getContactsFromURL () {
        try {
            CompletableFuture<ContactsResponse> cr = Main.getRestUserEndpoints().contacts.get();
            return cr.get();
        } catch (InterruptedException | ExecutionException e) {
            log.error("error getting contacts response", e);
            return null;
        }
    }
}

@@ -530,120 +530,157 @@
 om.g
-oogle.common.base.Supplier;%0Aimport com.google.common.base.Suppliers;%0Aimport com.google.common.cache.CacheBuilder
+ithub.benmanes.caffeine.cache.CacheLoader;%0Aimport com.github.benmanes.caffeine.cache.Caffeine;%0Aimport com.github.benmanes.caffeine.cache.LoadingCache
 ;%0Aim
@@ -702,31 +702,27 @@
 .common.
-cache.CacheLoad
+base.Suppli
 er;%0Aimpo
@@ -742,34 +742,30 @@
 .common.
-cache.LoadingCache
+base.Suppliers
 ;%0Aimport
@@ -1660,34 +1660,30 @@
 details = Ca
-cheBuilder
+ffeine
 .newBuilder(
@@ -2529,18 +2529,14 @@
 = Ca
-cheBuilder
+ffeine
 .new
@@ -3427,16 +3427,17 @@
 orServer
+ 
 (@Nonnul
@@ -3534,24 +3534,25 @@
 Id));%0A    %7D%0A
+%0A
     public v
@@ -3643,28 +3643,24 @@
 ) %7B%0A        
-    
 customServer
@@ -3803,34 +3803,16 @@
 erId) %7B%0A
-        try %7B%0A    
         
@@ -3867,154 +3867,8 @@
 ));%0A
-        %7D catch (ExecutionException e) %7B%0A            log.error(%22error getting details from cache%22, e);%0A        %7D%0A        return Optional.empty();%0A
     

use caffeine for caching instead of guava -- its faster