var transform = require("transform-js").transform;
var classes = require("class-manipulator").list;

var tools = require("../tools/tools");
var reveal = require("../tools/reveal");
var DisplayObject = require("../DisplayObject");

var truthy = tools.truthy;
var replaceVars = tools.replaceVariables;

function Textbox (asset) {

    this.z = 1000;

    DisplayObject.apply(this, arguments);

    var element, nameElement, textElement;

    this.type = asset.getAttribute("behaviour") || "adv";
    this.showNames = truthy(asset.getAttribute("namebox"));
    this.nltobr = truthy(asset.getAttribute("nltobr"));
    this.cssid = this.cssid || "wse_textbox_" + this.name;
    this.effectType = asset.getAttribute("effect") || "typewriter";
    this.speed = asset.getAttribute("speed") || 0;
    this.speed = parseInt(this.speed, 10);
    this.fadeDuration = asset.getAttribute("fadeDuration") || 0;

    (function (ctx) {

        var el, i, len, elms;

        try {

            elms = asset.childNodes;

            for (i = 0, len = elms.length; i < len; i += 1) {

                if (elms[i].nodeType === 1 && elms[i].tagName === 'nameTemplate') {
                    el = elms[i];
                    break;
                }
            }

            if (!el) {
                throw new Error('No nameTemplate found.');
            }

            ctx.nameTemplate = new XMLSerializer().serializeToString(el);
        }
        catch (e) {
            ctx.nameTemplate = '{name}: ';
        }
    }(this));

    if (this.type === "nvl") {
        this.showNames = false;
    }

    element = this.element;
    nameElement = document.createElement("div");
    textElement = document.createElement("div");

    element.setAttribute("class", "asset textbox");
    textElement.setAttribute("class", "text");
    nameElement.setAttribute("class", "name");

    element.appendChild(nameElement);
    element.appendChild(textElement);

    if (this.showNames === false) {
        nameElement.style.display = "none";
    }

    nameElement.setAttribute("id", this.cssid + "_name");
    textElement.setAttribute("id", this.cssid + "_text");

    this.nameElement = this.cssid + "_name";
    this.textElement = this.cssid + "_text";

    element.style.opacity = 0;

    this.bus.trigger("wse.assets.textbox.constructor", this);
}

Textbox.prototype = Object.create(DisplayObject.prototype);

Textbox.prototype.put = function (text, name, speakerId) {

    var textElement, nameElement, namePart, self, cssClass = "wse_no_character", element;

    name = name || null;
    speakerId = speakerId || "_no_one";

    self = this;
    textElement = document.getElementById(this.textElement);
    nameElement = document.getElementById(this.nameElement);
    element = document.getElementById(this.cssid);

    text = replaceVars(text, this.interpreter);

    self.interpreter.waitCounter += 1;

    namePart = "";

    if (this.showNames === false && !(!name)) {
        namePart = this.nameTemplate.replace(/\{name\}/g, name);
    }

    if (name === null) {

        if (this.showNames) {
            nameElement.style.display = "none";
        }

        name = "";
    }
    else {

        if (this.showNames) {
            nameElement.style.display = "";
        }

        cssClass = "wse_character_" + speakerId.split(" ").join("_");
    }

    if (this._lastCssClass) {
        classes(element).remove(this._lastCssClass).apply();
    }

    this._lastCssClass = cssClass;

    classes(element).add(cssClass).apply();

    if (this.speed < 1) {

        if (this.fadeDuration > 0) {

            self.interpreter.waitCounter += 1;

            (function () {

                var valFn, finishFn, options;

                valFn = function (v) {
                    textElement.style.opacity = v;
                };

                finishFn = function () {
                    self.interpreter.waitCounter -= 1;
                };

                options = {
                    duration: self.fadeDuration
                };

                transform(1, 0, valFn, options, finishFn);
            }());
        }
        else {
            putText();
        }
    }

    if (this.speed > 0) {

        if (self.type === 'adv') {
            textElement.innerHTML = "";
        }

        (function () {

            var container;

            container = document.createElement('div');
            container.setAttribute('class', 'line');
            textElement.appendChild(container);
            container.innerHTML = namePart + text;
            nameElement.innerHTML = self.nameTemplate.replace(/\{name\}/g, name);
            //self.interpreter.waitCounter += 1;

            self.interpreter.cancelCharAnimation = reveal(
                container, 
                { 
                    speed: self.speed,
                    onFinish: function () {
                        //self.interpreter.waitCounter -= 1; 
                        self.interpreter.cancelCharAnimation = null;
                    }
                }
            ).cancel;
        }());
    }
    else if (this.fadeDuration > 0) {

        self.interpreter.waitCounter += 1;

        setTimeout(
            function () {

                putText();

                if (self.type === 'nvl') {
                    textElement.innerHTML = '<div>' + textElement.innerHTML + '</div>';
                }

                transform(
                    0,
                    1,
                    function (v) {
                        textElement.style.opacity = v;
                    },
                    {
                        duration: self.fadeDuration,
                        onFinish: function () {
                            self.interpreter.waitCounter -= 1;
                        }
                    }
                );
            },
            self.fadeDuration
        );
    }

    this.bus.trigger("wse.assets.textbox.put", this, false);
    self.interpreter.waitCounter -= 1;

    return {
        doNext: false
    };

    function putText () {

        if (self.type === 'adv') {
            textElement.innerHTML = "";
        }

        textElement.innerHTML += namePart + text;
        nameElement.innerHTML = self.nameTemplate.replace(/\{name\}/g, name);
    }
};

Textbox.prototype.clear = function () {

    document.getElementById(this.textElement).innerHTML = "";
    document.getElementById(this.nameElement).innerHTML = "";
    this.bus.trigger("wse.assets.textbox.clear", this);

    return {
        doNext: true
    };
};

Textbox.prototype.save = function () {

    return {
        assetType: "Textbox",
        type: this.type,
        showNames: this.showNames,
        nltobr: this.nltobr,
        cssid: this.cssid,
        nameElement: this.nameElement,
        textElement: this.textElement,
        z: this.z
    };
};

Textbox.prototype.restore = function (save) {

    this.type = save.type;
    this.showNames = save.showNames;
    this.nltobr = save.nltobr;
    this.cssid = save.cssid;
    this.nameElement = save.nameElement;
    this.textElement = save.textElement;
    this.z = save.z;

    document.getElementById(this.cssid).style.zIndex = this.z;
};

module.exports = Textbox;

Documents

docs/reference/elements/nametemplate.md
docs/reference/elements/stop.md
docs/development.md
docs/documentation.md
docs/downloads.md
docs/examples.md
docs/games.md
docs/index.md
docs/reference/elements/alert.md
docs/reference/elements/animation.md
docs/reference/elements/assets.md
docs/reference/elements/audio.md
docs/reference/elements/background.md
docs/reference/elements/break.md
docs/reference/elements/character.md
docs/reference/elements/choice.md
docs/reference/elements/clear.md
docs/reference/elements/composite.md
docs/reference/elements/conditionals.md
docs/reference/elements/confirm.md
docs/reference/elements/curtain.md
docs/reference/elements/displayname.md
docs/reference/elements/do.md
docs/reference/elements/easing_attribute.md
docs/reference/elements/else.md
docs/reference/elements/flash.md
docs/reference/elements/flicker.md
docs/reference/elements/fn.md
docs/reference/elements/global.md
docs/reference/elements/globalize.md
docs/reference/elements/goto.md
docs/reference/elements/group.md
docs/reference/elements/hide.md
docs/reference/elements/image.md
docs/reference/elements/imagepack.md
docs/reference/elements/line.md
docs/reference/elements/localize.md
docs/reference/elements/move.md
docs/community.md
docs/reference/elements/option.md
docs/reference/elements/pause.md
docs/reference/elements/play.md
docs/reference/elements/prompt.md
docs/reference/elements/restart.md
docs/reference/elements/scene.md
docs/reference/elements/scenes.md
docs/reference/elements/set.md
docs/reference/elements/set_vars.md
docs/reference/elements/settings.md
docs/reference/elements/shake.md
docs/reference/elements/show.md
docs/reference/elements/source.md
docs/reference/elements/stage.md
docs/reference/elements/start.md
docs/beginners-guide.md
docs/reference/elements/sub.md
docs/reference/elements/tag.md
docs/reference/elements/textbox.md
docs/reference/elements/track.md
docs/reference/elements/transform.md
docs/reference/elements/trigger.md
docs/reference/elements/trigger_command.md
docs/reference/elements/triggers.md
docs/reference/elements/var.md
docs/reference/elements/wait.md
docs/reference/elements/when.md
docs/reference/elements/while.md
docs/reference/elements/with.md
docs/reference/elements/ws.md
docs/reference/elements.md
docs/reference/language.md
docs/reference/structure.md
docs/reference/syntax.md
docs/web-servers.md
libs/MO5/README.md
libs/MO5/libs/using.js/README.md
libs/MO5/js/EventBus.js
libs/MO5/js/Animation.js
libs/MO5/js/CoreObject.js
libs/MO5/js/Exception.js
libs/MO5/js/List.js
libs/MO5/js/MO5.js
libs/MO5/js/Map.js
libs/MO5/js/Point.js
libs/MO5/js/Promise.js
libs/MO5/js/Queue.js
libs/MO5/js/Result.js
libs/MO5/js/Set.js
libs/MO5/js/Size.js
libs/MO5/js/Timer.js
libs/MO5/js/TimerWatcher.js
libs/MO5/js/ajax.js
libs/MO5/js/assert.js
libs/MO5/js/dom.Element.js
libs/MO5/js/dom.effects.typewriter.js
libs/MO5/js/dom.escape.js
libs/MO5/js/easing.js
libs/MO5/js/fail.js
libs/MO5/js/globals.document.js
libs/MO5/js/globals.window.js
libs/MO5/js/range.js
libs/MO5/js/tools.js
libs/MO5/js/transform.js
libs/MO5/js/types.js
libs/MO5/libs/using.js/tests/index.js
libs/MO5/libs/using.js/tests/module1.js
libs/MO5/libs/using.js/tests/module2.js
libs/MO5/libs/using.js/tests/module3.js
libs/MO5/libs/using.js/using.js
libs/MO5/tests/node/EventBus.test.js
libs/MO5/tests/node/Set.test.js
src/savegames.js
src/tools/reveal.js
src/tools/ui.js
src/loader.js
src/tools/tools.js
src/tools/compile.js
src/functions.js
src/DisplayObject.js
src/Game.js
src/Interpreter.js
src/Keys.js
src/LoadingScreen.js
src/Trigger.js
src/assets/Audio.js
src/assets/Background.js
src/assets/Character.js
src/assets/Composite.js
src/assets/Curtain.js
src/assets/Imagepack.js
src/assets/Textbox.js
src/assets.js
src/bus.js
src/commands/alert.js
src/commands/break.js
src/commands/choice.js
src/commands/confirm.js
src/commands/do.js
src/commands/fn.js
src/commands/global.js
src/commands/globalize.js
src/commands/goto.js
src/commands/line.js
src/commands/localize.js
src/commands/prompt.js
src/commands/restart.js
src/commands/set_vars.js
src/commands/sub.js
src/commands/trigger.js
src/commands/var.js
src/commands/wait.js
src/commands/while.js
src/commands/with.js
src/commands.js
src/dataSources/LocalStorage.js
src/dataSources.js
src/engine.js
src/extensions/button.js
src/extensions/colored-rectangle.js
src/extensions/get-backtrace.js
src/extensions/hello.js
src/extensions/side-images.js
CHANGELOG.md
LICENSE.md
README.md
build.js
index.js
index.md
package.js