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

import server.Emote;
import server.Player;
import server.SyntaxException;

public class HelpCommand extends Command {

    private static final Map<String,String[]> helpTopics = new HashMap<String,String[]>();
    
    static {
        helpTopics.put("COLORS", new String[] {
            "Colors (Use @10F@@30Fabf@ZZZ in any output to change color)",
            "    a = attributes (1=@100bold@ZZZ, 2=@200italic@ZZZ, 4=@400underline@ZZZ)",
            "    b = background",
            "    f = foreground",
            "    Use @10FZ@ZZZ in place of a digit to use the default",
            "    For example, @10F@@10F2ZZ@ZZZ would use italics, but use default color.",
            "    Don't try to color-match manually please! Use the Z's!",
            "Color list: @1011 @1022 @1033 @1044 @1055 @1066 @1077 @1088 @1099 @10AA @10BB @10CC @10DD @10EE @10FF",
        });
        helpTopics.put("TOKENS", new String[] {
            "@10FThe Token System",
            "",
            "A token string consists of tokens and text. The tokens are like fill-in-the-blanks " +
            "that are filled in when the token string is resolved. When the token string is " +
            "resolved, it is supplied with a list of entities (items, players, or NPCs), and an " +
            "optional list of strings, depending on the circumstances.",
            "",
            "The # in the below text represents the entity number from the list of entities. Which " +
            "entity number refers to what is totally based on how the token string is being used, " +
            "but entity 0 is always the person observing the action. Entity 1 is usually the " +
            "source of the action, and entity 2 is usually the target of the action.",
            "",
            "@50FEntity Tokens",
            "",
            "    @10F%n#@ZZZ = nominative",
            "",
            "    @4ZZExamples@ZZZ: Joe, a large wendigo #3, an apple, you, Joe and Bob",
            "",
            "    @10F%a#@ZZZ = accusative pronoun",
            "",
            "    @4ZZExamples@ZZZ: him, her, it, you, them",
            "",
            "    @10F%p#@ZZZ = nominative pronoun",
            "",
            "    @4ZZExamples@ZZZ: he, she, it, you, they",
            "",
            "    @10F%x#@ZZZ = reflexive pronoun",
            "",
            "    @4ZZExamples@ZZZ:  himself, herself, itself, yourself, themselves",
            "",
            "    @10F%q#@ZZZ = possessive",
            "",
            "    @4ZZExamples@ZZZ: Joe's, a large wendigo #3's, an apple's, your, Joe's and Bob's",
            "",
            "    @10F%y#@ZZZ = possessive adjective",
            "",
            "    @4ZZExamples@ZZZ: his, her, its, your, their",
            "",
            "    @10F%z#@ZZZ = possessive pronoun",
            "",
            "    @4ZZExamples@ZZZ: his, hers, its, yours, theirs",
            "",
            "    @10F%w#@ZZZ = nominative with possessive name",
            "",
            "    @4ZZExamples@ZZZ: Joe's apple, an apple (if not being held by anyone)",
            "",
            "    @10F%u#@ZZZ = nominative with possessive pronoun",
            "",
            "    @4ZZExamples@ZZZ: his apple, an apple (if not being held by anyone)",
            "",
            "    An '@10FM@ZZZ' may be used to signify that the entity is combinable with " +
            "other token strings of the same type. For example, '@10F%MN1 %v1/bows/bow/.@ZZZ' " +
            "starts life as '@10FJoe bows.@ZZZ' but can become '@10FJoe and Mary bow.@ZZZ' if they both " +
            "happen to bow at the same time.",
            "",
            "    Capitalize a token to cause the entity it refers to to be capitalized. " +
            "For example, '@10F%n1 bows.@ZZZ' can be '@10FJoe bows.@ZZZ' or '@10Fa man bows.@ZZZ'. " +
            "Using '@10F%N1 bows.@ZZZ', however, ensures that '@10FA man bows.@ZZZ' is produced.",
            "",
            "@50FString substitutions",
            "",
            "    Usage: @10F%s#@ZZZ",
            "",
            "    In this case, the '@10F#@ZZZ' does not refer to an entity, but rather to a " +
            "string selection from the list of strings. Some token strings will have " +
            "a list of strings associated with them. @10F%s0@ZZZ selects the first string, " +
            "@10F%s1@ZZZ selects the second string, etc.",
            "",
            "@50FPlurality Pairs",
            "",
            "    Usage: @10F%v#/singular/plural/@ZZZ",
            "       or: @10F%r#/singular/plural/@ZZZ",
            "",
            "    Where @10F#@ZZZ is the entity number being tested for plurality. Any delimiter " +
            "can be used. '@10F/@ZZZ' is just an example. The only difference between @10F%v@ZZZ and " +
            "@10F%r@ZZZ is that @10F%v@ZZZ considers \"@10FYou@ZZZ\" to be plural, while @10F%r@ZZZ " +
            "does not.",
            "",
            "@50FNull Entities",
            "",
            "    Usage: @10F%?#/choice_if_not_null/choice_if_null/@ZZZ",
            "",
            "    Where @10F#@ZZZ is the entity number being tested for null. Any delimiter " +
            "can be used. '@10F/@ZZZ' is just an example.",
            "",
            "@50FComparisons",
            "",
            "    Usage: @10F%c#XYZ/choice_if_match/choice_if_no_match/@ZZZ",
            "    Usage: @10F%o#XYZ/choice_if_match/choice_if_no_match/@ZZZ",
            "",
            "    Any delimiter can be used. '@10F/@ZZZ' is just an example. If " +
            "entity number '@10F#@ZZZ' is the same as entity number '@10FX@ZZZ', '@10FY@ZZZ', or " +
            "'@10FZ@ZZZ', then use @10Fchoice_if_match@ZZZ, otherwise use @10Fchoice_if_no_match@ZZZ. " +
            "The difference between @10F%c@ZZZ and @10F%o@ZZZ is that @10F%o@ZZZ actually compares the " +
            "@3ZZowner@ZZZ of entity number '@10F#@ZZZ' with the list of entities.",
            "",
            "@50FExamples",
            "",
            "    @10F%MN1 %v1/arrives/arrive/ from the %s0.@ZZZ",
            "",
            "    @10F%N1 %v1/notices/notice/ %Mc21/%x2/%n2/ looking at %c321/%c31!%a3!%x3!/%n3/.@ZZZ",
            "",
        });
    }
    
    public HelpCommand() {
        super(CommandCategory.SYSTEM, "Accesses the help system.");
    }
    
    @Override
    public void run(Player player) throws SyntaxException {
        String token = CommandProcessor.nextToken();
        if (CommandProcessor.nextToken() != null) {
            throw new SyntaxException();
        }
        Set<CommandCategory> categories = player.getCommandCategories();
        if (token == null) {
            player.sendText(true, "The following command categories are available:");
            StringBuffer sb = new StringBuffer();
            if (player.canEmote()) {
                sb.append("EMOTES");
            }
            for (CommandCategory category : categories) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(category);
            }
            player.sendText(false, "@10F" + sb);
            player.sendText(true, "The following general help topics are available:");
            sb = new StringBuffer();
            for (String topic : helpTopics.keySet()) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(topic);
            }
            player.sendText(false, "@10F" + sb);
            player.sendText(true, "Type @10FHELP @30F<category@ZZZ|@30Ftopic>@ZZZ for further help.");
        }
        else {
            CommandCategory category = null;
            try {
                category = CommandCategory.valueOf(token.toUpperCase());
            }
            catch (IllegalArgumentException ex) {
                /* ignore */
            }
            if (categories.contains(category)) {
                player.showCommands(category);
            }
            else if (token.equals("emotes") && player.canEmote()) {
                StringBuffer sb = new StringBuffer();
                for (String name : Emote.list()) {
                    if (sb.length() > 0) {
                        sb.append(", ");
                    }
                    sb.append(name);
                }
                player.sendText(true, "You have the following @10FEMOTES@ZZZ:");
                player.sendText(true, "@10F" + sb);
                player.sendText(true, "Typing @10FHELP @30F<emote>@ZZZ will give you more information on a specific emote.");
            }
            else {
                String[] helpText = helpTopics.get(token.toUpperCase());
                if (helpText != null) {
                    player.sendText(false, "");
                    for (int i = 0; i < helpText.length; i++) {
                        player.sendText(false, helpText[i]);
                    }
                }
                else {
                    CommandProcessor.help(player, token);
                }
            }
        }
    }

    @Override
    public String[] getSyntax(Player player) {
        return new String[] { "", "<category>", "<command>", "TOPICS" };
    }

}