/// <reference path="../Action.ts" />
/// <reference path="../../../Elements/Classes/Say/SayBold.ts" />
/// <reference path="../../../Elements/Classes/Say/SayThe.ts" />
/// <reference path="../../../Elements/Modules/HyperlinkHandler.ts" />

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

    /**
     * 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 {Say}
     */
    public getCommandText () {
        return "take " + (this.getNoun(0) != undefined ? this.getNoun(0).getPrintedName() : "");
    }

    public static defaultCarryTakingRule = new Rule({
        name : "Taking - Add the thing to your inventory",
        code : (rulebook : RulebookRunner<ActionTake>) => {
            let action = <ActionGo> rulebook.noun;
            let actor = action.actor;
            let thing = (<Thing>action.getNoun(0));

            if (thing.getEnclosedOne() != undefined) {
                // Remove Part Of, Carried or Wielded. It's essentially stealing.
                Thing.EnclosedRelation.unsetRight(thing);
            } else {
                thing.removeFromRoom();
            }

            Thing.CarryRelation.setRelation(actor, action.getNoun(0));

            if (actor == WorldState.player) {
                action.say.add(new SayBold((<Thing> action.getNoun(0)).getPrintedName() + ": "), "Taken.");
            } else {
                action.say.add(new SayThe(), actor, " takes ", new SayThe(undefined, true), (<Thing> action.getNoun(0)), ".");
            }
        }
    });
}

ActionTake.check.addRule(
    new Rule({
        name : "Check Taking - Who has it, really?",
        priority : Rule.PRIORITY_HIGHEST,
        code : (rulebook : RulebookRunner<ActionTake>) => {
            let action = <ActionGo> rulebook.noun;
            let actor = action.actor;
            let thing = (<Thing>action.getNoun(0));
            let owner = <Thing> thing.getEnclosedOne();

            if (owner == actor){
                if (owner == WorldState.player) {
                    action.say.add("You already have it.");
                }
                return false;
            }
        }
    })
);

ActionTake.check.addRule(
    new Rule({
        name : "Check Taking - Donut steal",
        code : (rulebook : RulebookRunner<ActionTake>) => {
            let action = <ActionGo> rulebook.noun;
            let actor = action.actor;
            let thing = (<Thing>action.getNoun(0));
            let owner = <Thing> thing.getEnclosedOne();

            if (owner != undefined && owner.animated){
                if (actor == WorldState.player) {
                    action.say.add(owner.getPrintedName() + " wouldn't like that.");
                }
                return false;
            }
        }
    })
);

ActionTake.check.addRule(
    new Rule({
        name : "Check Taking - Can't take fixed in place",
        code : (rulebook : RulebookRunner<ActionTake>) => {
            let action = <ActionGo> rulebook.noun;
            let actor = action.actor;
            let thing = (<Thing>action.getNoun(0));

            if (thing.fixedInPlace){
                if (actor == WorldState.player) {
                    action.say.add("You can't take that.");
                }
                return false;
            }
        }
    })
);

ActionTake.carry.addRule(
    ActionTake.defaultCarryTakingRule
);

Elements.HyperlinkHandler.HyperlinkingRulebook.addRule(new Rule(
    {
        name : "Hyperlink - Take",
        firstPriority : Rule.PRIORITY_HIGHEST,
        code : (rulebook : RulebookRunner<Thing>) => {
            let thing = <Thing> rulebook.noun;

            if (!thing.animated && !thing.fixedInPlace && thing.getRoom() == WorldState.player.getRoom() && thing.getEnclosedOne() instanceof Room) {
                Elements.HyperlinkHandler.addAvailableAction("Take", new ActionTake(WorldState.player, thing));
            }
        }
    }
));