/// <reference path="../Action.ts" />
/// <reference path="../Rule.ts" />
/// <reference path="../Rulebook.ts" />

class ActionRetrace extends Action {
    public static check = new Rulebook<ActionRetrace>("Check Retracing");
    public static carry = new Rulebook<ActionRetrace>("Carry out Retracing");

    public constructor (actor : Thing, ...nouns : Array<any>) {
        super(actor, ...nouns);
        this.requiresNoun = false;
        this.requiresVisibility = false;
        this.requiresTurn = false;
    }

    /**
     * Needs to return a string explaining what the player will do if he does this action.
     * For instance, ActionTaking should return something like return "take " + this.nouns[0].getName(),
     *   which would read as "take thing".
     *   remember that things implement PRINTABLE interface, so you can get their names.
     * @returns {string}
     */
    public getCommandText () {
        let name;
        if (typeof this.getNoun(0) == "number") {
            name = DirectionNames[Direction[this.getNoun(0)]];
        } else if (this.getNoun(0) instanceof Room) {
            name = (<Room> this.getNoun(0)).getPrintedName();
        }
        return "think about how to get to " + name;
    }
}


ActionRetrace.check.addRule(new Rule({
    firstPriority : Rule.PRIORITY_HIGHEST,
    priority : Rule.PRIORITY_HIGH,
    name : "Change Room to Direction",
    code : (rulebook : RulebookRunner<ActionRetrace>) => {
        let action = <ActionGo> rulebook.noun;

        // Someone asked for a room...
        if (action.getNoun(0) instanceof Room) {
            let actor = action.actor;
            let cRoom = actor.getRoom();
            if (cRoom == undefined) {
                return false;
            }
            let dRoom = action.getNoun(0);

            if (cRoom == dRoom) {
                if (actor.isPlayer()) {
                    action.say.add("You are already there!");
                }
                action.stop();
                return false;
            }

            let code;

            if (actor == WorldState.player) {
                code = (room : Room) => {
                    return WorldState.isRoomRemembered(room);
                }
            }

            let direction = cRoom.bestDirectionTo(dRoom, code);
            if (direction == undefined) {
                if (actor.isPlayer()) {
                    action.say.add("You don't remember how to get there.");
                }
                return false;
            } else {
                action.setNoun(0, direction);
            }
        }
    }
}));

ActionRetrace.carry.addRule(new Rule({
    name : "Retracing - Find Direction",
    code : (rulebook : RulebookRunner<ActionRetrace>) => {
        let action = <ActionRetrace> rulebook.noun;

        action.say.add("To get there, you should go " + DirectionNames[Direction[action.getNoun(0)]] + ".");
    }
}));
