package de.simolzimol.mclogger.paper.listeners;

import de.simolzimol.mclogger.paper.PaperLoggerPlugin;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.HashMap;
import java.util.Map;

/**
 * Logs all block-related events: breaking, placing,
 * burning, exploding, igniting, signs, etc.
 *
 * @author SimolZimol
 */
public class BlockListener implements Listener {

    private final PaperLoggerPlugin plugin;

    public BlockListener(PaperLoggerPlugin plugin) {
        this.plugin = plugin;
    }

    // -------------------------------------------------------
    // Block Break
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onBreak(BlockBreakEvent event) {
        Player p = event.getPlayer();
        Block b = event.getBlock();
        ItemStack tool = p.getInventory().getItemInMainHand();

        boolean silkTouch = tool.hasItemMeta()
                && tool.getItemMeta() != null
                && tool.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH);

        String toolName = tool.getType().isAir() ? "HAND" : tool.getType().name();
        String blockData = b.getBlockData().getAsString();

        plugin.getDb().insertBlockEvent(
                "break",
                p.getUniqueId().toString(),
                p.getName(),
                b.getWorld().getName(),
                b.getX(), b.getY(), b.getZ(),
                b.getType().name(),
                blockData,
                toolName,
                silkTouch
        );
    }

    // -------------------------------------------------------
    // Block Place
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onPlace(BlockPlaceEvent event) {
        Player p = event.getPlayer();
        Block b = event.getBlockPlaced();

        plugin.getDb().insertBlockEvent(
                "place",
                p.getUniqueId().toString(),
                p.getName(),
                b.getWorld().getName(),
                b.getX(), b.getY(), b.getZ(),
                b.getType().name(),
                b.getBlockData().getAsString(),
                null, false
        );
    }

    // -------------------------------------------------------
    // Block Burn
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onBurn(BlockBurnEvent event) {
        Block b = event.getBlock();
        plugin.getDb().insertBlockEvent(
                "burn",
                null, null,
                b.getWorld().getName(),
                b.getX(), b.getY(), b.getZ(),
                b.getType().name(),
                b.getBlockData().getAsString(),
                null, false
        );
    }

    // -------------------------------------------------------
    // Block Ignite
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onIgnite(BlockIgniteEvent event) {
        Block b = event.getBlock();
        Player p = event.getPlayer();

        Map<String, Object> details = new HashMap<>();
        details.put("cause", event.getCause().name());

        plugin.getDb().insertBlockEvent(
                "ignite",
                p != null ? p.getUniqueId().toString() : null,
                p != null ? p.getName() : null,
                b.getWorld().getName(),
                b.getX(), b.getY(), b.getZ(),
                b.getType().name(),
                b.getBlockData().getAsString(),
                null, false
        );
    }

    // -------------------------------------------------------
    // Block Explosion
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onExplode(BlockExplodeEvent event) {
        Block b = event.getBlock();
        plugin.getDb().insertBlockEvent(
                "explode",
                null, null,
                b.getWorld().getName(),
                b.getX(), b.getY(), b.getZ(),
                b.getType().name(),
                b.getBlockData().getAsString(),
                null, false
        );
    }

    // -------------------------------------------------------
    // Sign Edit
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onSign(SignChangeEvent event) {
        Player p = event.getPlayer();
        Block b = event.getBlock();

        String[] lines = new String[4];
        for (int i = 0; i < 4; i++) {
            lines[i] = event.line(i) != null
                    ? PlainTextComponentSerializer.plainText().serialize(event.line(i))
                    : "";
        }

        plugin.getDb().insertSignEdit(
                p.getUniqueId().toString(),
                p.getName(),
                b.getWorld().getName(),
                b.getX(), b.getY(), b.getZ(),
                lines[0], lines[1], lines[2], lines[3]
        );
    }
}
