package me.km.snuviscript.commands;

import java.util.UUID;
import java.util.function.Consumer;
import me.hammerle.snuviscript.code.Script;
import me.hammerle.snuviscript.inputprovider.InputProvider;
import me.km.overrides.ModEntityPlayerMP;
import me.km.permissions.Permissions;
import me.km.playerbank.IPlayerBank;
import me.km.snuviscript.Scripts;
import me.km.utils.Location;
import me.km.utils.Utils;
import net.minecraft.block.BlockState;
import net.minecraft.command.ICommandSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.PlayerList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;

public class CommandUtils {
    private final static UUID SERVER_UUID = new UUID(0, 0);

    public static UUID getUUID(Object o) {
        if(o instanceof PlayerEntity) {
            return ((PlayerEntity) o).getUniqueID();
        } else if(o instanceof UUID) {
            return (UUID) o;
        } else if("SERVER".equals(o)) {
            return SERVER_UUID;
        }
        return UUID.fromString(o.toString());
    }

    public static ITextComponent concat(Script sc, int start, String pre, InputProvider... ob) throws Exception {
        StringTextComponent text = new StringTextComponent(pre);
        Object o;
        for(int i = start; i < ob.length; i++) {
            o = ob[i].get(sc);
            if(o instanceof ITextComponent) {
                text.appendSibling((ITextComponent) o);
            } else {
                text.appendText(String.valueOf(o));
            }
        }
        return text;
    }

    public static void sendMessageToGroup(MinecraftServer server, Scripts scripts, Permissions perms, Object group, Script sc, ITextComponent text) {
        doForGroup(server, scripts, perms, group, sc, p -> p.sendMessage(text));
    }

    public static void doForGroup(MinecraftServer server, Scripts scripts, Permissions perms, Object group, Script sc, Consumer<ICommandSource> c) {
        if(group instanceof String) {
            switch(group.toString().toLowerCase()) {
                case "all":
                    PlayerList list = server.getPlayerList();
                    if(list != null) {
                        scripts.getPlayerList(sc.getId()).forEach(uuid -> {
                            ServerPlayerEntity p = list.getPlayerByUUID(uuid);
                            if(p != null) {
                                c.accept(p);
                            }
                        });
                    }
                    break;
                case "online":
                    if(server.getPlayerList() != null) {
                        server.getPlayerList().getPlayers().forEach(p -> c.accept(p));
                    }
                    break;
                case "dev":
                    if(server.getPlayerList() != null) {
                        server.getPlayerList().getPlayers().forEach(p -> {
                            if(perms.has(p, "script.error")) {
                                c.accept(p);
                            }
                        });
                    }
                    break;
                case "server":
                    c.accept(server);
                    break;
                default:
                    if(server.getPlayerList() != null) {
                        c.accept(Utils.getPlayerByName(server, group.toString()));
                    }
                    break;
            }
            return;
        }
        c.accept((PlayerEntity) group);
    }

    public static int getId(IPlayerBank bank, Object o) {
        if(o instanceof ModEntityPlayerMP) {
            return ((ModEntityPlayerMP) o).getId();
        } else if(o instanceof Double) {
            return ((Double) o).intValue();
        }
        UUID uuid = getUUID(o);
        return bank.getId(uuid);
    }
    
    public static Class getNamedClass(String s) throws ClassNotFoundException {
        return Class.forName(s);
    }
    
    public static BlockState getBlockState(Location l) {
        return l.getWorld().getBlockState(l.getBlockPos());
    }
}
