/// <reference path="../Thing.ts" />
/// <reference path="../Action/ActionTake.ts" />
/// <reference path="../../../Elements/Modules/RoomHandler.ts" />

class CoinPouch extends Thing {
    private coins : number = 0;

    public addCoins (coins : number) {
        this.coins += coins;
    }

    public removeCoins (coins : number) {
        this.coins -= coins;
    }

    public getCoins () {
        return this.coins;
    }

    public getShiny () {
        return this.coins > 0;
    }

    public constructor (options : ThingOptions) {
        super(options);

        this.addGetAlterations((purse) => {
            return {
                coins : purse.getCoins()
            };
        });

        this.addSetAlterations((purse, changeObj) => {
            purse.coins = (changeObj.coins);
        });
    }

    public static carryOutTakingCoinPouches = new Rule({
        name : "Carry out taking coin pouches",
        firstPriority : ActionTake.defaultCarryTakingRule.firstPriority,
        priority : ActionTake.defaultCarryTakingRule.priority + 1,
        code : async (rulebook : RulebookRunner<ActionTake>) => {
            let action = <ActionTake> rulebook.noun;
            let actor = action.actor;
            let thing = (<CoinPouch>action.getNoun(0));
            let actorPouches = Thing.CarryRelation.getRightType(actor, CoinPouch);

            if (actorPouches.length > 0) {
                let thingCoins = thing.getCoins();
                if (thingCoins > 0) {
                    rulebook.skipRule(ActionTake.defaultCarryTakingRule);

                    (<CoinPouch> actorPouches[0]).addCoins(thingCoins);
                    thing.removeCoins(thing.getCoins());

                    if (actor == WorldState.player) {
                        action.say.add("You empty ", new SayThe(), thing, " into your ", actorPouches[0], ". Your ", actorPouches[0], " now has " + actorPouches[0].getCoins().toString() + " coins.");
                    } else {
                        action.say.add(new SayThe(), actor, " empties ", new SayThe(), thing, " into ", Say.hisHersIts(actor), actorPouches[0], ".");
                    }
                } else {
                    // give them the ol' switcharoo
                    let myCoins = actorPouches[0].getCoins();
                    actorPouches[0].removeCoins(myCoins);
                    thing.addCoins(myCoins);
                    if (actor == WorldState.player) {
                        action.say.add("You empty your ", actorPouches[0], " into ", new SayThe(), thing, ".", Say.PARAGRAPH_BREAK);
                    }
                    let drop = new ActionDrop(actor, actorPouches[0]);
                    await drop.execute();

                    if (Thing.EnclosedRelation.getLeft(actorPouches[0]) == actor) {
                        if (actor == WorldState.player) {
                            action.say.add("You can't get rid of your ", actorPouches[0], "!");
                        }
                        return false;
                    }
                }
            }
        },
        conditions : (rulebook : RulebookRunner<ActionTake>) => {
            return ((<ActionTake> rulebook.noun).getNoun(0) instanceof CoinPouch);
        }
    });
}

ActionTake.carry.addRule(CoinPouch.carryOutTakingCoinPouches);

Say.afterPrinting.addRule(new Rule(
    {
        name : "Include contents of Coin Pouch while Printing Visible Things in a Room",
        code : (rulebook : RulebookRunner<Say>) => {
            let say = <Say> rulebook.noun;
            let pouch = <CoinPouch> say.currentNoun;
            say.currentNounElements.push(document.createTextNode(" with " + pouch.getCoins().toString() + " coins"));
        },
        conditions : (rulebook : RulebookRunner<Say>) => {
            return Elements.RoomHandler.PrintingVisibleThingsRulebook.isRunning()
                && (<Say> rulebook.noun).currentNoun instanceof CoinPouch
                && (<CoinPouch> (<Say> rulebook.noun).currentNoun).getCoins() > 0;
        }
    }
));

ActionExamine.carry.addRule(new Rule({
    name : "Print description of coins in Coin Pouch",
    firstPriority : ActionExamine.PrintDescriptionOfExaminedThingRule.firstPriority,
    priority : ActionExamine.PrintDescriptionOfExaminedThingRule.priority - 1,
    code : (rulebook : RulebookRunner<ActionExamine>) => {
        let action = <ActionExamine> rulebook.noun;
        let thing = <CoinPouch> action.getNoun(0);
        if (thing.getCoins() > 0) {
            action.say.add(" There are " + thing.getCoins().toString() + " coins in it.");
        } else {
            action.say.add(" There are no coins in it.");
        }
    },
    conditions : (rulebook : RulebookRunner<ActionExamine>) => {
        return ((<ActionExamine> rulebook.noun).getNoun(0) instanceof CoinPouch);
    }
}));