package tc.oc.commons.bukkit.debug;

import javax.annotation.Nullable;
import javax.inject.Inject;

import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import java.time.Duration;
import tc.oc.api.bukkit.users.BukkitUserStore;
import tc.oc.api.docs.virtual.Model;
import tc.oc.api.model.ModelDispatcher;
import tc.oc.api.model.ModelListener;
import tc.oc.commons.core.plugin.PluginFacet;
import tc.oc.debug.LeakDetector;

public class LeakListener implements PluginFacet, Listener, ModelListener {

    private static final Duration DEADLINE = Duration.ofSeconds(10);

    private final LeakDetector leakDetector;
    private final BukkitUserStore userStore;

    @Inject LeakListener(LeakDetector leakDetector, BukkitUserStore userStore, ModelDispatcher modelDispatcher) {
        this.leakDetector = leakDetector;
        this.userStore = userStore;
        modelDispatcher.subscribe(this);
    }

    @HandleModel
    public void modelUpdated(@Nullable Model before, @Nullable Model after, Model latest) {
        if(before != null && before != after) {
            leakDetector.expectRelease(before, DEADLINE, true);
        }
    }

    @EventHandler(priority = EventPriority.LOWEST)
    public void onLogout(PlayerQuitEvent event) {
        leakDetector.expectRelease(event.getPlayer(), DEADLINE, true);
        leakDetector.expectRelease(userStore.tryUser(event.getPlayer()), DEADLINE, true);
        leakDetector.expectRelease(userStore.getSession(event.getPlayer()), DEADLINE, true);
    }

    @EventHandler(priority = EventPriority.LOWEST)
    public void onWorldChange(WorldUnloadEvent event) {
        leakDetector.expectRelease(event.getWorld(), DEADLINE, true);
    }
}
