package com.skcraft.plume.common.module;

import com.google.inject.Inject;
import com.sk89q.worldedit.util.eventbus.Subscribe;
import com.skcraft.plume.common.UserId;
import com.skcraft.plume.common.service.auth.*;
import com.skcraft.plume.common.service.ban.BanManager;
import com.skcraft.plume.common.util.config.Config;
import com.skcraft.plume.common.util.config.InjectConfig;
import com.skcraft.plume.common.event.lifecycle.InitializationEvent;
import com.skcraft.plume.common.util.service.ServiceLocator;
import com.skcraft.plume.common.util.module.Module;
import com.skcraft.plume.common.service.party.PartyCache;
import com.skcraft.plume.common.service.party.PartyManager;
import com.skcraft.plume.common.service.sql.DatabaseBans;
import com.skcraft.plume.common.service.sql.DatabaseHive;
import com.skcraft.plume.common.service.sql.DatabaseManager;
import com.skcraft.plume.common.service.sql.DatabaseParties;
import lombok.Getter;
import ninja.leaping.configurate.objectmapping.Setting;

@Module(name = "mysql-services")
public class MySQLServices {

    @InjectConfig("mysql/services")
    private Config<ServicesConfig> config;

    private final MySQLPool pool;
    private final ServiceLocator services;

    @Getter private Hive hive;
    @Getter private BanManager bans;
    @Getter private PartyManager parties;
    @Getter private UserCache userCache;
    @Getter private PartyCache partyCache;

    @Inject
    public MySQLServices(MySQLPool pool, ServiceLocator services) {
        this.pool = pool;
        this.services = services;
    }

    @Subscribe
    public void onInitializationEvent(InitializationEvent event) {
        DatabaseManager database = pool.getDatabase();
        database.setDataSchema(config.get().schema);

        (hive = new DatabaseHive(database)).load();
        (bans = new DatabaseBans(database)).load();
        (parties = new DatabaseParties(database)).load();

        services.register(Hive.class, hive);
        services.register(BanManager.class, bans);
        services.register(PartyManager.class, parties);

        // Not the ideal way to do it but we'll have to manage for now
        services.register(UserCache.class, userCache = new UserCache(hive));
        services.register(PartyCache.class, partyCache = new PartyCache(parties));

        services.register(Authorizer.class, new HiveAuthorizer());
    }

    private class HiveAuthorizer implements Authorizer {
        @Override
        public Subject getSubject(UserId userId) {
            User user = userCache.getUserIfPresent(userId);
            if (user != null) {
                return user.getSubject();
            } else {
                return NoAccessSubject.INSTANCE;
            }
        }
    }

    private static class ServicesConfig {
        @Setting(comment = "The schema/database name for the user/bans/etc. tables")
        private String schema = "plume_data";
    }

}

@@ -160,16 +160,85 @@
 UserId;%0A
+import com.skcraft.plume.common.event.lifecycle.InitializationEvent;%0A
 import c
@@ -369,153 +369,88 @@
 mon.
-util.config.Config;%0Aimport com.skcraft.plume.common.util.config.InjectConfig;%0Aimport com.skcraft.plume.common.event.lifecycle.InitializationEvent
+service.claim.ClaimCache;%0Aimport com.skcraft.plume.common.service.claim.ClaimMap
 ;%0Aim
@@ -483,21 +483,16 @@
 mon.
-util.
 service.
 Serv
@@ -487,30 +487,32 @@
 service.
-ServiceLocator
+party.PartyCache
 ;%0Aimport
@@ -541,26 +541,34 @@
 mon.
-util.module.Module
+service.party.PartyManager
 ;%0Aim
@@ -605,32 +605,21 @@
 service.
-party.PartyCache
+sql.*
 ;%0Aimport
@@ -648,34 +648,24 @@
 mon.
-service.party.PartyManager
+util.Environment
 ;%0Aim
@@ -698,32 +698,26 @@
 mon.
-service.sql.DatabaseBans
+util.config.Config
 ;%0Aim
@@ -750,32 +750,32 @@
 mon.
-service.sql.DatabaseHive
+util.config.InjectConfig
 ;%0Aim
@@ -808,35 +808,26 @@
 mon.
-service.sql.DatabaseManager
+util.module.Module
 ;%0Aim
@@ -852,32 +852,37 @@
 lume.common.
+util.
 service.
 sql.Database
@@ -873,27 +873,22 @@
 ice.
-sql.DatabaseParties
+ServiceLocator
 ;%0Aim
@@ -1183,16 +1183,59 @@
 ervices;
+%0A    private final Environment environment;
 %0A%0A    @G
@@ -1334,24 +1334,63 @@
 er parties;%0A
+    @Getter private ClaimMap claimMap;%0A
     @Getter 
@@ -1460,16 +1460,59 @@
 tyCache;
+%0A    @Getter private ClaimCache claimCache;
 %0A%0A    @I
@@ -1581,16 +1581,41 @@
 services
+, Environment environment
 ) %7B%0A    
@@ -1666,24 +1666,64 @@
 = services;%0A
+        this.environment = environment;%0A
     %7D%0A%0A    @
@@ -2069,16 +2069,101 @@
 .load();
+%0A        (claimMap = new DatabaseClaims(database, environment.getServerId())).load();
 %0A%0A      
@@ -2307,16 +2307,69 @@
 arties);
+%0A        services.register(ClaimMap.class, claimMap);
 %0A%0A      
@@ -2592,16 +2592,112 @@
 rties));
+%0A        services.register(ClaimCache.class, claimCache = new ClaimCache(claimMap, partyCache));
 %0A%0A      

Load claims in the MySQL Services module.