/// <reference path="../Elements.ts" />
/// <reference path="../../World/Classes/Action/ActionExamine.ts" />
/// <reference path="../../World/Classes/Action/ActionGo.ts" />
module Elements.RoomHandler {
    export var currentRoomTab = document.getElementById("currentRoomTab");
    export var currentRoomDescription = document.getElementById("roomDescription");
    export var currentRoomExits = document.getElementById("roomExits");

    export var currentRoomName : Text = document.createTextNode("");
    document.getElementById("roomName").appendChild(currentRoomName);

    export function linkObjects () {
        let objs = currentRoomTab.getElementsByClassName("roomObject");

        for (let i = 0; i < objs.length; i++) {
            let linkKeyCode = Controls.KeyHandler.getFirstKeyCode();
            Controls.KeyHandler.applyCode(<HTMLElement> objs[i], linkKeyCode);
        }
    }

    export function emptyRoom () {
        while (currentRoomDescription.firstChild) {
            currentRoomDescription.removeChild(currentRoomDescription.firstChild);
        }

        while (currentRoomExits.firstChild) {
            currentRoomExits.removeChild(currentRoomExits.firstChild);
        }

        currentRoomName.nodeValue = "";
    }

    export async function updateRoom () {
        emptyRoom();

        let room = WorldState.player.getRoom();

        if (room != undefined) {
            currentRoomName.nodeValue = room.getPrintedName();

            let description = room.description.getHTML("p", ["roomDescription"]);
            await description.then(value => {
                for (let i = 0, p = value[i]; p != undefined; p = value[++i]) {
                    currentRoomDescription.appendChild(p);
                }
            });

            let things = room.getContainedAndVisible();
            if (things.length > 0) {
                let thingList = document.createElement("p");
                thingList.classList.add("roomDescription");

                await PrintingVisibleThingsRulebook.execute({
                    noun : <VisibleThingsOptions> {
                        things : things,
                        container : thingList
                    }
                });

                currentRoomDescription.appendChild(thingList);
            }

            for (let index = 0, value = room.connections[index]; index < room.connections.length; value = room.connections[++index]) {
                if (value != undefined) {
                    let p = document.createElement("p");
                    p.classList.add("roomExit");

                    let link = document.createElement("a");
                    link.classList.add("roomDirection");
                    link.appendChild(document.createTextNode(DirectionNames[Direction[index]]));

                    Controls.Links.makeLink(link, new ActionGo(WorldState.player, index));
                    Controls.KeyHandler.applyCode(link, Controls.KeyHandler.getDirectionCodeByIndex(index));

                    p.appendChild(link);

                    let directionResult = ": ";
                    if (WorldState.isRoomRemembered(value)) {
                        directionResult += value.getPrintedName();
                    } else {
                        directionResult += "A new place";
                    }

                    p.appendChild(document.createTextNode(directionResult));

                    currentRoomExits.appendChild(p);
                }
            }
        }
    }

    export interface VisibleThingsOptions {
        container : HTMLElement,
        things : Array<Thing>
    }

    /**
     * Noun = VisibleThingsOptions
     * @type {Rulebook}
     */
    export var PrintingVisibleThingsRulebook = new Rulebook("Printing the name of visible things in a room");

    export var PrintIntroToVisibleThingsRule = new Rule({
        name : "Print \"You can see\" text",
        firstPriority : Rule.PRIORITY_HIGH,
        code : (rulebook : RulebookRunner<VisibleThingsOptions>) =>  {
            let noun = <VisibleThingsOptions> rulebook.noun;
            noun.container.appendChild(document.createTextNode("You can see "));
        }
    });
    PrintingVisibleThingsRulebook.addRule(PrintIntroToVisibleThingsRule);

    export var PrintVisibleThingsRule = new Rule({
        name : "Print all visible things",
        code : async (rulebook : RulebookRunner<VisibleThingsOptions>) => {
            let noun = <VisibleThingsOptions> rulebook.noun;
            for (let i = 0; i < noun.things.length; i++) {
                let value = noun.things[i];
                let link = document.createElement("a");
                link.classList.add("roomObject");

                let say : Say
                if (value instanceof Thing && value.unique) {
                    say = new Say(new SayThe(false), value);
                } else {
                    say = new Say(new SayAn(false), value);
                }
                await say.getPureElements().then(value2 => {
                    for (let i = 0, element = value2[i]; element != undefined; element = value2[++i]) {
                        link.appendChild(element);
                    }
                });

                Controls.Links.makeLink(link, new ActionExamine(WorldState.player, value));
                Controls.KeyHandler.applyCode(link, Controls.KeyHandler.getFirstKeyCode());

                noun.container.appendChild(link);

                if ((i + 1) < noun.things.length) {
                    noun.container.appendChild(document.createTextNode(", "));
                }
            }
        }
    });
    PrintingVisibleThingsRulebook.addRule(PrintVisibleThingsRule);

    export var PrintOutroToVisibleThingsRule = new Rule({
        name : "Print \"... here\" text",
        firstPriority : Rule.PRIORITY_LOW,
        code : (rulebook : RulebookRunner<VisibleThingsOptions>) =>  {
            let noun = <VisibleThingsOptions> rulebook.noun;
            noun.container.appendChild(document.createTextNode(" here."));
        }
    });
    PrintingVisibleThingsRulebook.addRule(PrintOutroToVisibleThingsRule);
}