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

class ActionInventory extends Action {
    public requiresTurn = false;
    public requiresNoun = false;
    public requiresVisibility = false;

    public static check : Rulebook<ActionInventory> = new Rulebook("Check Taking Inventory");
    public static carry : Rulebook<ActionInventory> = new Rulebook("Carry out Taking Inventory");

    /**
     * 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 inventory";
    }

    public static async createButton (thing : Thing, resolve : (t : Thing) => void) {
        let p = document.createElement("p");
        p.classList.add("choice");
        let elements = await ((new Say(thing)).getPureElements());
        elements.forEach(ele => {
            p.appendChild(ele);
        });

        p.addEventListener("click", () => {
            resolve(thing);
        });

        Controls.KeyHandler.applyCode(p, Controls.KeyHandler.getFirstKeyCode());

        return p;
    }

    public static checkInventoryRule = ActionInventory.check.createAndAddRule({
        name : "List inventory as options",
        code : async (rulebook : RulebookRunner<ActionTake>) => {
            let player = WorldState.player;
            let wielded = Thing.WieldRelation.getRight(player).sort(Elements.InventoryHandler.thingSort);
            let worn = Thing.WearRelation.getRight(player).sort(Elements.InventoryHandler.thingSort);
            let carried = Thing.CarryRelation.getRight(player).sort(Elements.InventoryHandler.thingSort);

            let buttons;
            let chosenPromise = new Promise((async resolve => {
                Controls.KeyHandler.reset();
                let say = new Say();
                if (wielded.length > 0) {
                    say.add(new SayBold("Wielded:"), Say.LINE_BREAK);
                    for (let i = 0; i < wielded.length; i++) {
                        say.add(await ActionInventory.createButton(wielded[i], resolve));
                    }
                }

                if (worn.length > 0) {
                    if (say.sequence.length > 0) {
                        say.add(Say.PARAGRAPH_BREAK);
                    }
                    say.add(new SayBold("Worn:"), Say.LINE_BREAK);
                    for (let i = 0; i < worn.length; i++) {
                        say.add(await ActionInventory.createButton(worn[i], resolve));
                    }
                }

                if (carried.length > 0) {
                    if (say.sequence.length > 0) {
                        say.add(Say.PARAGRAPH_BREAK);
                    }
                    say.add(new SayBold("Carried:"), Say.LINE_BREAK);
                    for (let i = 0; i < carried.length; i++) {
                        say.add(await ActionInventory.createButton(carried[i], resolve));
                    }
                }

                if (say.sequence.length == 0) {
                    return resolve(undefined);
                }

                buttons = await say.getHTMLContent();
                Elements.CurrentTurnHandler.print(...(buttons));
            }));

            let chosenThing = await chosenPromise;
            if (chosenThing != undefined) {
                Elements.CurrentTurnHandler.unprint(...buttons);
                Controls.KeyHandler.reset();
                return new ActionExamine(WorldState.player, chosenThing);
            } else {
                rulebook.noun.say.add("You have nothing.");
                return false;
            }
        }
    });
}

Elements.HyperlinkHandler.CommonActionsRulebook.addRule(new Rule({
    name : "Add Take Inventory Command Rule",
    firstPriority : Rule.PRIORITY_LOWEST,
    priority : Rule.PRIORITY_MEDIUM,
    code : (rulebook : RulebookRunner<void>) => {
        Elements.HyperlinkHandler.addCommonAction("Inventory", new ActionInventory(WorldState.player));
    }
}));