/*
Copyright (C) 2005 David Green <green@couchpotato.net>
All Rights Reserved.

This file is part of Aelfengard.

Aelfengard is proprietary software. You may not redistribute it without
prior written permission from the copyright holder.
*/

package server.command;

import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

import server.AdminFlag;
import server.Player;
import server.SyntaxException;
import server.token.TokenString;

public class AdminFlagsCommand extends Command {

    private static final TokenString TS_ON_FLAGS = new TokenString("%N1 %v1/has/have/ the following admin flags:");
    private static final TokenString TS_OFF_FLAGS = new TokenString("%N1 %v1/does/do/ @2ZZNOT@ZZZ have the following admin flags:");
    
    private final boolean canModify;
    
    public AdminFlagsCommand(boolean canModify) {
        super(CommandCategory.ADMIN, "Set or query admin flags for a user.");
        this.canModify = canModify;
    }
    
    @Override
    public void run(Player player) throws SyntaxException {
        String name = CommandProcessor.nextToken();
        if (name == null) {
            // show a list of all admin flags
            player.sendText(true, "The following admin flags are available:");
            showFlags(player, EnumSet.allOf(AdminFlag.class), "@10F");
            return;
        }
        Player target = player.getPlayerByNickname(name);
        if (target == null) {
            player.sendText(true, "Unknown player: " + name);
            return;
        }
        boolean isAdd;
        String subcmd = CommandProcessor.nextToken();
        if (subcmd == null) {
            // show flags for specified player
            Set<AdminFlag> onFlags = target.getAdminFlags();
            Set<AdminFlag> offFlags = EnumSet.allOf(AdminFlag.class);
            offFlags.removeAll(onFlags);
            player.sendText(true, null, null, null, TS_ON_FLAGS, null, target);
            showFlags(player, onFlags, "@10A");
            player.sendText(true, null, null, null, TS_OFF_FLAGS, null, target);
            showFlags(player, offFlags, "@109");
            return;
        }
        else if (!canModify) {
            throw new SyntaxException();
        }
        else if (subcmd.equals("add")) {
            isAdd = true;
        }
        else if (subcmd.equals("remove")) {
            isAdd = false;
        }
        else {
            throw new SyntaxException();
        }
        Set<AdminFlag> flags = new HashSet<AdminFlag>();
        while (true) {
            String perm = CommandProcessor.nextToken();
            if (perm == null) {
                break;
            }
            perm = perm.toUpperCase();
            AdminFlag flag = null;
            try {
                flag = AdminFlag.valueOf(perm);
            }
            catch (IllegalArgumentException ex) {
                player.sendText(true, "Unknown admin flag: " + perm);
                return;
            }
            // player #1 can modify the ADMIN_FLAGS flag, or a user can add/remove it
            // from themselves (remove it, really)
            if (flag == AdminFlag.ADMIN_FLAGS && player.getId() != 1 && player != target) {
                player.sendText(true, "The ADMIN_FLAGS flag cannot be modified.");
                return;
            }
            if (!player.getAdminFlags().contains(flag)) {
                player.sendText(true, "You must possess the " + flag + " flag in order to modify it with this command.");
                return;
            }
            flags.add(flag);
        }
        if (flags.isEmpty()) {
            throw new SyntaxException();
        }
        for (AdminFlag flag : flags) {
            target.setAdminFlag(flag, isAdd);
        }
        player.sendText(true, "Admin flags changed.");
    }

    private static void showFlags(Player player, Set<AdminFlag> flags, String prefix) {
        StringBuffer sb = new StringBuffer();
        for (AdminFlag flag : flags) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(flag);
        }
        if (sb.length() == 0) {
            player.sendText(false, prefix + "<none>");
        }
        else {
            player.sendText(false, prefix + sb);
        }
    }
    
    @Override
    public String[] getSyntax(Player player) {
        return new String[] { 
                "",
                "<user>",
                "<user> ADD <flags...>",
                "<user> REMOVE <flags...>",
        };
    }
    
}