package jesse.keeblarcraft.Commands;

import com.mojang.brigadier.arguments.StringArgumentType;

import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.ConfigMgr.GeneralConfig;
import jesse.keeblarcraft.Utils.DirectionalVec;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.math.Vec3d;

public class MiscCommands {
    ConfigManager config = new ConfigManager();

    public void RegisterCommands() {
        // CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {

        //     var magicInv = CommandManager.literal("magic-inv").build();
        //     var claim = CommandManager.literal("claim").executes(context -> ClaimInventory(context.getSource().getPlayer())).build();

        //     dispatcher.getRoot().addChild(magicInv);
        //     magicInv.addChild(claim);
        // });

        // CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {

        //     var eChest = CommandManager.literal("enderchest").build();
        //     var player = CommandManager.argument("PLAYER", EntityArgumentType.player()).executes(
        //         context -> GetEnderchestOfPlayer(context.getSource().getPlayer(), EntityArgumentType.getPlayer(context, "PLAYER"))
        //     ).build();

        //     dispatcher.getRoot().addChild(eChest);
        //     eChest.addChild(player);

        //     // Alias
        //     dispatcher.register(CommandManager.literal("echest").redirect(eChest));
        // });

        CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {

            var forceSpawn = CommandManager.literal("set-global-spawn").executes(context -> ForceGlobalSpawn(context.getSource().getPlayer())).build();

            dispatcher.getRoot().addChild(forceSpawn);
        });

        CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {

            var warp = CommandManager.literal("warp").build();

            var warpLoc = CommandManager.argument("LOCATION", StringArgumentType.string())
            .executes(context -> Warp(context.getSource().getPlayer(), StringArgumentType.getString(context, "LOCATION"))).build();

            dispatcher.getRoot().addChild(warp);
            warp.addChild(warpLoc);
        });

        CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {

            var warp = CommandManager.literal("nick").build();

            var warpLoc = CommandManager.argument("CUSTOM_NICKNAME", StringArgumentType.string())
            .executes(context -> SetNickname(context.getSource().getPlayer(), StringArgumentType.getString(context, "CUSTOM_NICKNAME"))).build();

            dispatcher.getRoot().addChild(warp);
            warp.addChild(warpLoc);
        });
    }

    public int Warp(ServerPlayerEntity player, String location) {

        if (player.hasPermissionLevel(4)) {
            System.out.println("Player is opped");
            // hard coding spawn as only valid warp location. a more robust warp system can come later
            DirectionalVec coords = GeneralConfig.GetInstance().GetSpawnCoords();

            // DIRTY HACK: I am unsure how to compare the straight registry key. So for now, we will just iterate over all the worlds in the server. This really should
            // not be a big deal since I have never seen a server with hundreds of worlds... but you never know I guess.
            for (ServerWorld world : player.getServer().getWorlds()) {
                System.out.println("Matched!");
                if (world.getRegistryKey().toString().equals(coords.world.toString())) {
                    try {
                        player.teleport(world, coords.x, coords.y, coords.z, coords.yaw, coords.pitch);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                } else {
                    System.out.println("KEY {" + world.getRegistryKey() + "} DID NOT MATCH OURS {" + coords.world + "}");
                }
            }

            System.out.println("POST TELEPORT");
        } else {
            player.sendMessage(Text.of("This command is only available to server admins at the moment!"));
        }

        return 0;
    }

    public int ForceGlobalSpawn(ServerPlayerEntity player) {
        if (player.hasPermissionLevel(4)) {
            Vec3d coords = player.getPos();
            DirectionalVec spawnVec = new DirectionalVec();
            spawnVec.x = coords.x;
            spawnVec.y = coords.y;
            spawnVec.z = coords.z;
            spawnVec.pitch = player.getPitch();
            spawnVec.yaw = player.getYaw();
            spawnVec.world = player.getWorld().getRegistryKey();
            System.out.println("REG KEY OF SET: " + player.getWorld().getRegistryKey().toString());
            System.out.println("REG KEY OF SET: " + player.getWorld().getRegistryKey());
            player.sendMessage(Text.of("Global spawn has been set to [X, Y, Z]--[YAW, PITCH]: [" +
            spawnVec.x + " " + spawnVec.y + " " + spawnVec.z + "]--" + "[" + spawnVec.yaw + " " + spawnVec.pitch + "]" + " IN WORLD " +
            player.getWorld().asString()));

            GeneralConfig.GetInstance().SetSpawnCoords(spawnVec);
        } else {
            player.sendMessage(Text.of("You do not have permission to use this command."));
        }

        return 0;
    }

    public int SetNickname(ServerPlayerEntity player, String name) {
        player.setCustomName(Text.of(name));
        player.setCustomNameVisible(true);
        return 0;
    }

    public int GetEnderchestOfPlayer(ServerPlayerEntity cmdInitiator, ServerPlayerEntity targetPlayer) {

        // if (cmdInitiator.hasPermissionLevel(4)) {
            // EnderChestInventory enderInv = targetPlayer.getEnderChestInventory();
            // enderInv.

        // } else {

        // }

        return 0;
    }

    // public int ClaimInventory(ServerPlayerEntity player) {
    //     Vec3d playerPosition = player.getPos();
    //     BlockPos blockPosition = new BlockPos((int) playerPosition.x + 4, (int) playerPosition.y, (int) playerPosition.z).east();
    //     BlockPos blockPosition2 = new BlockPos((int) playerPosition.x + 3, (int) playerPosition.y, (int) playerPosition.z).east();


    //     // Verify we can place the blocks before loading cached inventory
    //     if (player.getWorld().setBlockState(blockPosition, chestState)
    //             && player.getWorld().setBlockState(blockPosition2, chestState)) {

    //         // The below code WILL remove the inventory from the dimension cache. Only get
    //         // it when we succeed in placing chests!
    //         NbtList nbtInventory = DimensionLoadingEvent.GetInstance().GetInventory(player.getUuidAsString());
    //         if (nbtInventory != null) {
    //             BlockEntity block = player.getWorld().getBlockEntity(blockPosition);
    //             BlockEntity block2 = player.getWorld().getBlockEntity(blockPosition2);

    //             if (block != null && block2 != null) {
    //                 block.markDirty();
    //                 block2.markDirty();
    //             }

    //             player.sendMessage(Text.of("Look around, your magic inventory chest was placed near you!"));
    //         }
    //     } else {
    //         player.sendMessage(Text.of("Well, this is embarassing! Could not place magic inventory chest near you!"));
    //     }

    //     return 0;
    // }
}
