var ScrollableDiv = {
    scrolls : {},
    clearAll : function() {
        for (var pane in this.scrolls) {
            this.get(pane).clear();
        }
    },
    get : function(id) {
        var pane = this.scrolls[id];
/*
        if (pane == null) {
            var mensaje = "Scroll ["+id+"] no encontrado. Scrolls disponibles:\n";
            for (pane in this.scrolls) {
                mensaje = mensaje+"["+pane+"] ";
            }
            alert(mensaje);
        }
*/
        return pane;
    },
    createTag : function(tag, id, className, inner) {
        return new Element(tag, {
            'id': id,
            'class': className}).setHTML(inner);
/*
        var element = document.createElement(tag);
        if (id) element.id = id;
        if (className) element.className = className;
        if (inner) element.innerHTML = inner;
        return element;
*/
    },

    createInputTag : function(tag, id, className, type, name) {
        return new Element(tag, {
            'id': id,
            'class': className,
            'autocomplete' : 'off',
            'type' : type,
            'name' : name});
        /*
        var element = document.createElement(tag);
        if (id) element.id = id;
        if (className) element.className = className;
        if (type) element.type = type;
        if (name) element.name = name;
    //    if (size) element.size = size;
        element.setAttribute('autocomplete','off');
        return element;
        */
    }

}

ScrollableDiv.Pane = function(id, config) {

    this.id = id;
    // Id del <form> para crearlo y borrarlo
    this.formId = id + "_formId";
    // Id y name del <input> del form, para poder obtener el valor
    this.inputTextNameAndId = id + "_inputText";
    this.inputPrompt = id + "_inputTextPrompt";
    this.divBlockPrefixId = id + "_block";

    this.history = [];
    this.currentHistory = "";
    this.historyPos = -1;
    this.bottomThreshold = -1;
    this.count = 0;

    this.max = 40;
    this.defaultPrompt = ">> ";
    this.onSendFunc = function(scroll){
        scroll.appendHeader(this.defaultPrompt + scroll.getPromptContent());
        scroll.createPrompt(this.defaultPrompt);
    };
    this.fixedPrompt = null;
    this.prompt = true;
    this.config = config?config:{}

    if (config) {
        if (config.max) {
            this.max = config.max;
        }
        if (config.fixedPrompt) {
            this.fixedPrompt = config.fixedPrompt;
        }
        if (config.onSendFunc) {
            this.onSendFunc = config.onSendFunc;
        }
        if (config.defaultPrompt) {
            this.defaultPrompt = config.defaultPrompt;
        }
        if (config.prompt != null) {
            this.prompt = config.prompt;
        }
    }

    ScrollableDiv.scrolls[id] = this;

}

ScrollableDiv.Pane.prototype.toString = function() {
    return "ScrollableDiv.Pane id:"+id;
}

ScrollableDiv.Pane.prototype.scrollToBottom = function() {
    var scrollDiv = $(this.id);
    var currentHeight = 0;

    if (scrollDiv.scrollHeight > 0) {
//        alert(currentHeight+" "+scrollDiv.scrollHeight);
        currentHeight = scrollDiv.scrollHeight;
    } else {
        // Safari
        if (scrollDiv.offsetHeight > 0) {
            currentHeight = scrollDiv.offsetHeight;
        }
    }

    var dif = scrollDiv.style.pixelHeight ? scrollDiv.style.pixelHeight : scrollDiv.offsetHeight;

//    alert(((currentHeight - scrollDiv.scrollTop - dif))+" < "+this.bottomThreshold+" "+((currentHeight - scrollDiv.scrollTop - dif) < this.bottomThreshold))

    // Esta condicion sirve para que si el usuario sube el scroll y el div es actualizado,
    // no se le baje y pueda seguir leyendo sin molestar (util en un chat, donde no se para
    // de recibir informacion)
    // Indicando un bottomThreshold de -1, forzamos a que siempre se haga scroll
    if (this.bottomThreshold == -1 || (currentHeight - scrollDiv.scrollTop - dif) < this.bottomThreshold) {
        // El verdadero scroll to botoom es esta linea:
        scrollDiv.scrollTop = currentHeight;
    }
    scrollDiv = null;
}

ScrollableDiv.Pane.prototype.appendHeader = function (content) {
    var block = ScrollableDiv.createTag("div", this.divBlockPrefixId + this.count, "block");

    if (content && content.length > 0) {
        var line = ScrollableDiv.createTag("div", null, "header", content);
        block.appendChild(line);
    }

    this.__appendWindow(block)
    return block;
}

ScrollableDiv.Pane.prototype.appendText = function (content) {
    if (!(content && content.length > 0)) return;
    var parent = $(this.divBlockPrefixId + this.count);
//        alert(id+".append '"+content+"' "+content.length)
    if (!parent) {
        parent = this.appendHeader();
    }

    var wrapper = ScrollableDiv.createTag("div", this.divBlockPrefixId + "_body_" + this.count);
    var newDiv = ScrollableDiv.createTag("div", null, "responseText", content)
    wrapper.appendChild(newDiv);
    parent.appendChild(wrapper);
    return wrapper;
}

ScrollableDiv.Pane.prototype.append = function (newDiv) {
    var parent = $(this.divBlockPrefixId + this.count);
//        alert(id+".append '"+newDiv+"'")
    if (!parent) {
        parent = this.appendHeader();
    }

    var wrapper = ScrollableDiv.createTag("div", this.divBlockPrefixId + "_body_" + this.count);
    wrapper.appendChild(newDiv);

    parent.appendChild(wrapper);
    return wrapper;
}

ScrollableDiv.Pane.prototype.ensurePrompt = function (prompt) {
    if (!this.prompt) {
        return;
    }
    if ($(this.formId) == null) {
        this.createPrompt(prompt);
    }
}

ScrollableDiv.Pane.prototype.submit = function(phrase) {
    if (!this.prompt) {
        return;
    }
    this.ensurePrompt()
    var form = $(this.formId);
    if (form != null) {
        if (phrase != null) {
            this.getPromptField().value = phrase;
        }
        form.onsubmit();
    }
}

ScrollableDiv.Pane.prototype.createPrompt = function (prompt) {
    try {
        if (!this.prompt) {
            return;
        }
        this.removePrompt();
        if (this.count >= this.max) {
    //        alert(this.divBlockPrefixId + (this.count + 1 - this.max))
            this.remove(this.divBlockPrefixId + (this.count + 1 - this.max));
        }
        this.count ++;

        var form = ScrollableDiv.createTag("form", this.formId);
        form.style.padding = 0;
        form.style.margin = 0;
        form.onsubmit = function(e) {
            var value = this.getPromptContent();
            this.history.push(value);
            this.historyPos = -1;
            this.currentHistory = "";
    //        try {
                this.onSendFunc(this);
    //        } catch (e) {
    //            alert("onSendFunc exception: "+e);
    //        }
            return false;
        }.bind(this);

        if (this.fixedPrompt != null) {
            $(this.fixedPrompt).appendChild(form);
        } else {
            this.__appendWindow(form);
        }

        prompt = prompt ? prompt : this.defaultPrompt;
        this.defaultPrompt = prompt;
        var promptWidth = 0;
        if (prompt) {
            var extra = ScrollableDiv.createTag("div", this.inputPrompt, "defaultPrompt", prompt);
            extra.style.display = "inline";
            form.appendChild(extra);
            this.promptWidth = this.getDimensions(this.inputPrompt).width;
        }

        var inputControl = ScrollableDiv.createInputTag("input", this.inputTextNameAndId, "promptInput", "text", this.inputTextNameAndId);

        form.appendChild(inputControl);

        inputControl.onkeyup = this.keyUp.bindAsEventListener(this);

        // Ajusta el tamaño del <input>
        var containerWidth = this.getDimensions(this.id).width;
        //    alert(containerWidth+" "+this.promptWidth+" "+((containerWidth - promptWidth)-12));
        $(this.inputTextNameAndId).style.width = (containerWidth - promptWidth) - 30 + "px";

        this.focus();
    } catch (e) {
        alert("Error en createPrompt:"+e);
    }
}

ScrollableDiv.Pane.prototype.removePrompt = function () {
    if (!this.prompt) {
        return;
    }
    var result = "";
    if ($(this.formId) != null) {
        result = this.getPromptContent();
        this.remove(this.formId);
    }
    return result;
}

ScrollableDiv.Pane.prototype.getPromptContent = function () {
    if (!this.prompt) {
        return;
    }
    return $(this.inputTextNameAndId).value;
}

ScrollableDiv.Pane.prototype.getPromptField = function () {
    if (!this.prompt) {
        return;
    }
    return $(this.inputTextNameAndId);
}

ScrollableDiv.Pane.prototype.getCount = function () {
    return this.count;
}

ScrollableDiv.Pane.prototype.focus = function () {
    this.scrollToBottom();
    if ($(this.inputTextNameAndId) != null)
        $(this.inputTextNameAndId).focus();
}

ScrollableDiv.Pane.prototype.changeSize = function (w, h) {
    this.setStyle(this.id, "width", w);
    this.setStyle(this.id, "height", h);
    this.scrollToBottom();
    $(this.inputTextNameAndId).focus();
}

ScrollableDiv.Pane.prototype.changeWidth = function (c) {
    var dim = this.getDimensions(this.id);
    var tot = dim.width + c;
//    if (tot < 1000 && tot > 300) {
        this.setStyle(this.id, "width", tot);
        this.scrollToBottom();
        $(this.inputTextNameAndId).focus();
//    }
}

ScrollableDiv.Pane.prototype.changeHeight = function (c) {
    var dim = this.getDimensions(this.id);
    var tot = dim.height + c;
//    if (tot < 800 && tot > 100) {
        this.setStyle(this.id, "height", tot);
        this.scrollToBottom();
        $(this.inputTextNameAndId).focus();
//    }
}


ScrollableDiv.Pane.prototype.moveHistory = function (dir) {
    // totally bogus value
    try {
        if (dir == 0 || this.history.length == 0) {
            return;
        }
        var elem = $(this.inputTextNameAndId);
        if (this.historyPos == -1) {
            this.currentHistory = elem.value;
            if (dir > 0) {
                return;
            }
            this.historyPos = this.history.length - 1;
            elem.value = this.history[this.historyPos];
            return;
        }
        if (this.historyPos == 0 && dir < 0) {
            return;
        }
        if (this.historyPos == this.history.length - 1 && dir > 0) {
            this.historyPos = -1;
            elem.value = this.currentHistory;
            return;
        }
        this.historyPos += dir;
        elem.value = this.history[this.historyPos];
    } catch (e) {
        alert("moveHistory exception:"+e);
    }
}

ScrollableDiv.Pane.prototype.keyUp = function (e) {
    try {
        var key = e.which;
        if (!key) key = e.keyCode
        // if any meta key is pressed, don't handle the signal
        switch (key) {
            case 38: this.moveHistory(-1); break;
            case 40: this.moveHistory(1); break;
            default: return;
        }
    } catch (e) {
        alert("keyUp exception:"+e);
    }
}

ScrollableDiv.Pane.prototype.__appendWindow = function (toAppend) {
    if ($(this.id) == null) {
        alert("Error:"+this.id+" no existe")
    } else {
        $(this.id).appendChild(toAppend);
    }
}

ScrollableDiv.Pane.prototype.update = function(id, content) {
//    alert(id);
//    alert(document.getElementById(id));
//    alert($(id));
//    alert($(id));
//    Element.inject(id, content, "bottom");
    $(id).setText(content);
}

ScrollableDiv.Pane.prototype.remove = function(id) {
    try {
        var el = $(id);
        if (el != null) {
            // Solo borramos el elemento si existe...
            el.remove();
        }
    } catch (e) {
        alert("Error en createPrompt:"+e);
    }
}

ScrollableDiv.Pane.prototype.getDimensions = function(id) {
    return $(id).getCoordinates();
}

ScrollableDiv.Pane.prototype.setStyle = function(id, key, value) {
    $(id).setStyle(key, value)
}

ScrollableDiv.Pane.prototype.clear = function (text) {
    this.update(this.id, '');
    this.count = 0;
    this.appendHeader(text);
}