package me.km.snuviscript;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import me.hammerle.snuviscript.code.Script;
import me.hammerle.snuviscript.inputprovider.Variable;
import me.km.permissions.Command;
import me.km.utils.Utils;
import net.minecraft.command.ICommandSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.server.MinecraftServer;

public class CommandScript extends Command {
    private final Scripts scripts;
    private final MinecraftServer server;

    public CommandScript(Scripts scripts, MinecraftServer server) {
        this.scripts = scripts;
        this.server = server;
    }

    @Override
    public String getName() {
        return "script";
    }

    @Override
    public Iterable<String> getAliases() {
        ArrayList<String> list = new ArrayList<>();
        list.add("s");
        return list;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void execute(ICommandSource cs, String[] arg) {
        if(arg.length >= 1) {
            switch(arg[0].toLowerCase()) {
                case "s":
                case "start": {
                    if(arg.length >= 2) {
                        String[] pars = Arrays.copyOfRange(arg, 1, arg.length);
                        scripts.startScript(null, pars);
                        return;
                    }
                    break;
                }
                case "startp": {
                    if(arg.length >= 3) {
                        PlayerEntity p = Utils.getPlayerByName(server, arg[1]);
                        if(p == null) {
                            sendMessage(cs, String.format("Cannot find player '%s'.", arg[1]));
                            return;
                        }
                        String[] pars = Arrays.copyOfRange(arg, 2, arg.length);
                        scripts.startPlayerScript(p, pars);
                        return;
                    }
                    break;
                }
                case "v":
                case "variable": {
                    if(arg.length >= 3) {
                        try {
                            Script sc = scripts.getScriptManager().getScript(Integer.parseInt(arg[1]));
                            if(sc == null) {
                                throw new NumberFormatException();
                            }
                            Variable var = sc.getVar(arg[2]);
                            if(var != null) {
                                sendMessage(cs, String.format("%s = %s", arg[2], var.get(sc)));
                            } else {
                                sendMessage(cs, String.format("%s = null", arg[2]));
                            }
                        } catch(NumberFormatException ex) {
                            sendMessage(cs, String.format("'%s' is not a valid id.", arg[1]));
                        }
                        return;
                    }
                    break;
                }
                case "see": {
                    Collection<Script> scs = scripts.getScriptManager().getScripts();
                    if(scs.isEmpty()) {
                        sendMessage(cs, "No scripts are active.");
                        return;
                    }
                    sendMessage(cs, "Active scripts:");
                    scs.forEach(sc -> {
                        String id = String.valueOf(sc.getId());
                        sendListMessage(cs, id, sc.getName());
                        scripts.getPlayerList(sc.getId()).forEach(uuid -> {
                            ServerPlayerEntity p = server.getPlayerList().getPlayerByUUID(uuid);
                            sendListMessage(cs, id, p == null ? "null" : p.getName().getFormattedText());
                        });
                    });
                    return;
                }
                case "term": {
                    if(arg.length >= 2) {
                        try {
                            if(arg[1].equals("all")) {
                                scripts.clearPlayerRegistry();
                                scripts.getScriptManager().removeScripts();
                                sendMessage(cs, "All active scripts were terminated.");
                                return;
                            }
                            int id = Integer.parseInt(arg[1]);
                            Script sc = scripts.getScriptManager().getScript(id);
                            if(sc != null) {
                                scripts.getScriptManager().removeScript(sc);
                                sendMessage(cs, String.format("Script '%s' was terminated.", sc.getName()));
                            } else {
                                sendMessage(cs, String.format("Script id '%d' is not valid.", id));
                            }
                        } catch(NumberFormatException ex) {
                            sendMessage(cs, String.format("'%s' is not a valid id.", arg[1]));
                        } catch(Exception ex) {
                            sendMessage(cs, "An exception on script termination was thrown.");
                            ex.printStackTrace();
                        }
                        return;
                    }
                    break;
                }
            }
        }

        sendMessage(cs, "/script ...");
        sendListMessage(cs, "start <scripts...>", "starts a script");
        sendListMessage(cs, "startp <player> <scripts...>", "starts a player script");
        sendListMessage(cs, "variable <id> <name>", "shows the value of a variable");
        sendListMessage(cs, "see", "shows active scripts");
        sendListMessage(cs, "term <id/all>", "terminates a script");
    }
}
