package eu.mhsl.minecraft.pixelblocks;

import co.aikar.taskchain.BukkitTaskChainFactory;
import co.aikar.taskchain.TaskChain;
import co.aikar.taskchain.TaskChainFactory;
import eu.mhsl.minecraft.pixelblocks.commands.PixelBlocksCommand;
import org.bukkit.command.PluginCommand;
import eu.mhsl.minecraft.pixelblocks.listeners.*;
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public final class Main extends JavaPlugin {
    private static Main plugin;
    private static PixelBlockConfiguration configuration;
    private static PixelBlockDatabase database;

    private static TaskChainFactory taskFactory;

    public final static List<PixelBlock> pixelBlocks = new CopyOnWriteArrayList<>();

    public static <T> TaskChain<T> sharedChain(String name) {
        return taskFactory.newSharedChain(name);
    }

    @Override
    public void onLoad() {
        Main.plugin = this;

        FileConfiguration config = this.getConfig();
        PixelBlockConfiguration.setDefaults(config);
        this.saveConfig();

        Main.configuration = new PixelBlockConfiguration(
            config.getInt(PixelBlockConfiguration.Keys.PixelsPerBlock.getKey()),
            config.getBoolean(PixelBlockConfiguration.Keys.OnlyBreakableByOwners.getKey()),
            config.getBoolean(PixelBlockConfiguration.Keys.OnlyEditableByOwners.getKey())
        );

        File databaseFile = new File(plugin.getDataFolder(), "blocks.db");
        Main.database = new PixelBlockDatabase("jdbc:sqlite:" + databaseFile);
    }

    @Override
    public void onEnable() {
        Translations.register();
        Main.taskFactory = BukkitTaskChainFactory.create(this);
        getLogger().info("Start constructing blocks from Database...");
        database.loadPixelBlocks();
        getLogger().info("Construction done!");

        Listener[] listeners = {
            new EnterPixelBlockListener(),
            new FallOutOfPixelBlockListener(),
            new BreakPixelListener(),
            new PlacePixelBlockListener(),
            new PreventInventoriesListener(),
            new ExitPixelWorldListener(),
            new PreventIllegalBlocksListener(),
            new BreakPixelBlockListener(),
            new PlacePixelListener(),
            new PreventHopperActionsListener(),
            new PreventLiquidsFlowListener(),
            new PreventRedstoneListener(),
            new PreventEntityPlacementListener(),
            new DiscoverRecipesListener(),
            new QuitWhileInPixelBlockListener(),
            new PreventGrowthListener(),
            new CraftPixelBlockListener()
        };

        for(Listener listener : listeners) {
            getServer().getPluginManager().registerEvents(listener, plugin);
        }

        PixelBlocksCommand pixelBlocksCommand = new PixelBlocksCommand();
        PluginCommand rootCommand = Objects.requireNonNull(getCommand("pixelblocks"));
        rootCommand.setExecutor(pixelBlocksCommand);
        rootCommand.setTabCompleter(pixelBlocksCommand);

        Bukkit.addRecipe(PixelBlockItem.getRecipe());
    }

    @Override
    public void onDisable() {
        Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld);
        taskFactory.shutdown(5, TimeUnit.SECONDS);
        database.close();
        Translations.unregister();
    }

    public static Main plugin() {
        return plugin;
    }

    public static Logger logger() {
        return plugin.getLogger();
    }

    public static PixelBlockDatabase database() {
        return database;
    }

    public static PixelBlockConfiguration configuration() {
        return configuration;
    }
}
