/*
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.Iterator;
import java.util.Map;

import server.AdminFlag;
import server.GameServer;
import server.Player;
import server.SyntaxException;
import server.Utils;

import com.aelfengard.i3.ChanInfo;
import com.aelfengard.i3.I3NotConnectedException;
import com.aelfengard.i3.LPCMixed;
import com.aelfengard.i3.MudInfo;
import com.aelfengard.i3.packet.ChannelMPacket;
import com.aelfengard.i3.packet.TellPacket;

public class I3Command extends Command {

    public I3Command() {
        super(CommandCategory.COMMUNICATION,
              "Communicate on the InterMUD-3 network.",
              "",
              "Be sure to place MUD names that contain spaces \"in quotes\"."
        );
    }
    
    @Override
    public void run(Player player) throws SyntaxException {
        String token = CommandProcessor.nextTokenPreserveCase();
        if (token == null) {
            // send I3 status to player
            String status = GameServer.i3client.isConnected() ? "@10ACONNECTED" : "@109DOWN";
            player.sendText(true, "@10FThe InterMUD-3 system is currently " + status);
            StringBuffer sb = new StringBuffer();
            for (String channel : player.getI3Channels()) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(channel);
            }
            if (sb.length() > 0) {
                player.sendText(true, "You're listening on the following channels:");
                player.sendText(false, "@10F" + sb.toString());
            }
            else {
                player.sendText(true, "You're not listening on any channels.");
            }
        }
        else if (token.equalsIgnoreCase("list")) {
            token = CommandProcessor.nextToken();
            if (token == null) {
                throw new SyntaxException();
            }
            else if (token.equals("muds")) {
                Map<String,MudInfo> muds = GameServer.i3client.getMudList();
                // remove down muds
                Iterator<Map.Entry<String,MudInfo>> iter = muds.entrySet().iterator();
                while (iter.hasNext()) {
                    if (iter.next().getValue().getState().asInteger() != MudInfo.MUD_STATE_UP) {
                        iter.remove();
                    }
                }
                boolean admin = player.getAdminFlags().contains(AdminFlag.ADMIN_VIEWS);
                String[] headers = new String[admin ? 4 : 3];
                headers[0] = "MUD Name";
                headers[1] = "Open Status";
                headers[2] = "Type/Driver/BaseMudLib/MudLib";
                if (admin) {
                    headers[3] = "Admin Email";
                } 
                String[][] data = new String[muds.size()][];
                int idx = 0;
                int upCount = 0;
                for (Map.Entry<String,MudInfo> entry : muds.entrySet()) {
                    MudInfo info = entry.getValue();
                    String[] values = new String[headers.length];
                    boolean isUp = info.getState().asInteger() == MudInfo.MUD_STATE_UP;
                    if (isUp) {
                        upCount++;
                    }
                    values[0] = (isUp ? "" : "(?) ") + entry.getKey();
                    values[1] = info.getOpenStatus().asString();
                    values[2] = info.getMudType() + "/" + info.getDriver() + "/" + info.getBaseMudLib() + "/" + info.getMudLib();
                    if (admin) {
                        values[3] = info.getAdminEmail().asString();
                    }
                    data[idx++] = values;
                }
                player.sendTable(data, headers, null);
                player.sendText(true, data.length + " muds listed.");
            }
            else if (token.equals("channels")) {
                Map<String,ChanInfo> channels = GameServer.i3client.getChannelList();
                String[] headers = { "Channel Name", "Host MUD" };
                String[][] data = new String[channels.size()][];
                int idx = 0;
                for (Map.Entry<String,ChanInfo> entry : channels.entrySet()) {
                    ChanInfo info = entry.getValue();
                    String name = entry.getKey();
                    switch (info.getChannelType()) {
                    case ChanInfo.CHANNEL_TYPE_SELECTIVELY_ADMITTED:
                        name += " (P)";
                        break;
                    case ChanInfo.CHANNEL_TYPE_SELECTIVELY_ADMITTED_AND_FILTERED:
                        name += " (PF)";
                        break;
                    }
                    String[] values = { name, info.getHostMud() };
                    data[idx++] = values;
                }
                player.sendTable(data, headers, null);
                player.sendText(true, data.length + " channels listed.");
                player.sendText(true, "(P) = Private, (PF) = Private & Filtered");
            }
            else {
                throw new SyntaxException();
            }
        }
        else if (token.equalsIgnoreCase("add")) {
            String channel = CommandProcessor.nextTokenPreserveCase();
            if (channel == null) {
                throw new SyntaxException();
            }
            player.addI3Channel(channel);
        }
        else if (token.equalsIgnoreCase("remove")) {
            String channel = CommandProcessor.nextTokenPreserveCase();
            if (channel == null) {
                throw new SyntaxException();
            }
            player.removeI3Channel(channel);
        }
        else if (token.equalsIgnoreCase("info")) {
            String mudname = CommandProcessor.getRemainingAllowQuotes();
            if (mudname == null) {
                throw new SyntaxException();
            }
            MudInfo info = GameServer.i3client.getMudInfo(mudname);
            if (info == null) {
                player.sendText(true, "Mud not found.");
                return;
            }
            String downString;
            if (info.getState() == null || info.getState().asInteger() != MudInfo.MUD_STATE_UP) {
                downString = " (@109DOWN@ZZZ)";
            }
            else {
                downString = "";
            }
            player.sendText(true, "@ZZZ@10F------------");
            player.sendText(false, "@ZZZ@10F       Name: @ZZZ" + mudname + downString);
            player.sendText(false, "@ZZZ@10F     Status: @ZZZ" + info.getOpenStatus());
            if (info.getPlayerPort().asInteger() > 0) {
                player.sendText(false, "@ZZZ@10F     Telnet: @ZZZ" + 
                        info.getIpAddr() + " port " + info.getPlayerPort());
            }
            player.sendText(false, "@ZZZ@10F      Admin: @ZZZ" + info.getAdminEmail());
            player.sendText(false, "@ZZZ@10F       Type: @ZZZ" + info.getMudType());
            player.sendText(false, "@ZZZ@10F     Driver: @ZZZ" + info.getDriver());
            player.sendText(false, "@ZZZ@10FBase MudLib: @ZZZ" + info.getBaseMudLib());
            player.sendText(false, "@ZZZ@10F     MudLib: @ZZZ" + info.getMudLib());
            player.sendText(false, "@ZZZ@10F------------");
        }
        else if (token.equalsIgnoreCase("who")) {
            String mudname = CommandProcessor.getRemainingAllowQuotes();
            if (mudname == null) {
                throw new SyntaxException();
            }
            try {
                GameServer.i3client.sendWho(new LPCMixed(player.getUsername()), new LPCMixed(mudname));
            } catch (I3NotConnectedException e) {
                player.sendText(true, "I3 system is down. Please try again later.");
            }
        }
        else if (token.equalsIgnoreCase("tell")) {
            String who = CommandProcessor.nextTokenAllowQuotes();
            if (who == null) {
                throw new SyntaxException();
            }
            int idx = who.indexOf('@');
            if (idx < 0) {
                throw new SyntaxException();
            }
            String mudname = who.substring(idx + 1);
            who = who.substring(0, idx);
            if (who.length() == 0 || mudname.length() == 0) {
                throw new SyntaxException();
            }
            String message = CommandProcessor.getRemaining();
            message = message.trim();
            if (message.length() == 0) {
                throw new SyntaxException();
            }
            message = Utils.prettyMessage(message);
            TellPacket packet = new TellPacket();
            packet.setOriginatorUsername(new LPCMixed(player.getUsername().toLowerCase()));
            packet.setOrigVisName(new LPCMixed(Utils.capitalize(player.getUsername())));
            packet.setTargetMudName(new LPCMixed(mudname));
            packet.setTargetUsername(new LPCMixed(who.toLowerCase()));
            packet.setMessage(new LPCMixed(message));
            try {
                GameServer.i3client.send(packet);
                player.sendText(true, "@00B@10A[@10Fi3@10A] @ZZZYou tell " + who + "@@ZZZ" + Utils.quoteIfSpace(mudname) + ", \"" + message + "@ZZZ\"");                
            }
            catch (I3NotConnectedException ex) {
                player.sendText(true, "I3 system is down. Could not send message.");
            }
        }
        else if (player.getI3Channels().contains(token)) {
            // token is channel name
            String msg = CommandProcessor.getRemaining().trim();
            if (msg.length() == 0) {
                throw new SyntaxException();
            }
            ChannelMPacket packet = new ChannelMPacket();
            packet.setChannelName(new LPCMixed(token));
            packet.setMessage(new LPCMixed(Utils.prettyMessage(msg)));
            packet.setOriginatorUsername(new LPCMixed(player.getUsername().toLowerCase()));
            packet.setVisName(new LPCMixed(Utils.capitalize(player.getUsername())));
            try {
                GameServer.i3client.send(packet);
            }
            catch (I3NotConnectedException ex) {
                player.sendText(true, "I3 system is down. Could not send message.");
            }
        }
        else {
            throw new SyntaxException();
        }
    }

    @Override
    public String[] getSyntax(Player player) {
        return new String[] {
                "",
                "LIST <MUDS|CHANNELS>",
                "ADD <channel>",
                "REMOVE <channel>",
                "INFO <mudname>",
                "WHO <mudname>",
                "TELL <player>@<mudname> <message>",
                "<channel> <message>",
                };
    }

}