package com.namelessmc.plugin.bukkit;

import com.namelessmc.plugin.bukkit.hooks.PapiHook;
import com.namelessmc.plugin.bukkit.hooks.PapiWrapper;
import com.namelessmc.plugin.bukkit.hooks.PlaceholderCacher;
import com.namelessmc.plugin.bukkit.hooks.maintenance.KennyMaintenance;
import com.namelessmc.plugin.bukkit.hooks.maintenance.MaintenanceStatusProvider;
import com.namelessmc.plugin.common.LanguageHandler;
import com.namelessmc.plugin.common.NamelessPlugin;
import com.namelessmc.plugin.common.logger.JulLogger;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.nio.file.Path;

public abstract class BukkitNamelessPlugin extends JavaPlugin {
	
	private @Nullable PapiWrapper papiWrapper;
	public @Nullable PapiWrapper papiWrapper() { return this.papiWrapper; }

	private @Nullable MaintenanceStatusProvider maintenanceStatusProvider;
	public @Nullable MaintenanceStatusProvider getMaintenanceStatusProvider() { return this.maintenanceStatusProvider; }

	protected final @NonNull NamelessPlugin plugin;

	private final @NonNull PlaceholderCacher placeholderCacher;

	public BukkitNamelessPlugin(String platformInternalName) {
		final Path dataDirectory = this.getDataFolder().toPath();
		this.plugin = new NamelessPlugin(
				dataDirectory,
				new BukkitScheduler(this),
				config -> new JulLogger(config, this.getLogger()),
				Path.of("logs", "latest.log"),
				platformInternalName,
				Bukkit.getVersion()
		);
		this.plugin.registerReloadable(new BukkitDataSender(this.plugin, this));
		this.plugin.registerReloadable(new UserSyncTask(this.plugin, this));
		this.placeholderCacher = this.plugin.registerReloadable(
				new PlaceholderCacher(this, this.plugin)
		);
		this.plugin.registerPermissionAdapter(new VaultPermissions(this.plugin));
	}

	@Override
	public void onEnable() {
		this.configureAudiences();

		this.plugin.reload();

		initPapi();
		initMaintenance();
		new Metrics(this, 13396);

		BukkitCommandProxy.registerCommands(this.plugin, this);

		this.getServer().getPluginManager().registerEvents(new BukkitEventProxy(this.plugin), this);
	}

	protected abstract void configureAudiences();

	public abstract void kickPlayer(final @NonNull Player player, final LanguageHandler.@NonNull Term term);
	
	private void initPapi() {
		if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
			final PapiHook placeholders = new PapiHook(this.placeholderCacher);
			placeholders.register();
			this.papiWrapper = new PapiWrapper();
		} else {
			this.papiWrapper = null;
		}
	}
	
	private void initMaintenance() {
		if (!Bukkit.getPluginManager().isPluginEnabled("Maintenance")) {
			return;
		}

		Plugin plugin = Bukkit.getPluginManager().getPlugin("Maintenance");
		if (!plugin.getDescription().getAuthors().contains("kennytv")) {
			return;
		}

		final String version = plugin.getDescription().getVersion();
		if (!version.startsWith("4")) {
			this.plugin.logger().warning("Ignoring unsupported KennyTV Maintenance version: " +
					version);
			return;
		}

		this.maintenanceStatusProvider = new KennyMaintenance();
	}

}

@@ -1662,24 +1662,74 @@
 sion()%0A%09%09);%0A
+%09%09this.plugin.registerReloadable(this::initPapi);%0A
 %09%09this.plugi
@@ -1783,32 +1783,32 @@
 plugin, this));%0A
-
 %09%09this.plugin.re
@@ -2147,22 +2147,8 @@
 );%0A%0A
-%09%09initPapi();%0A
 %09%09in
@@ -2530,24 +2530,24 @@
 nitPapi() %7B%0A
-
 %09%09if (Bukkit
@@ -2603,16 +2603,133 @@
 PI%22)) %7B%0A
+%09%09%09if (this.papiWrapper != null) %7B%0A%09%09%09%09// Placeholders were already registered in a previous reload%0A%09%09%09%09return;%0A%09%09%09%7D%0A
 %09%09%09final

Initialize papi during reload (onEnable) stage