Form.Element.Serializers.selectOne = function(element) {
    var value = '', opt, index = element.selectedIndex;
    if (index >= 0) {
        opt = element.options[index];
        value = opt.value;
    }
    return [element.name, value];
}

Form.Element.Serializers.selectMany = function(element) {
    var value = [];
    for (var i = 0; i < element.length; i++) {
        var opt = element.options[i];
        if (opt.selected)
            value.push(opt.value || opt.text);
    }
    return [element.name, value];
}

Object.extend(Event, {
    _domReady : function() {
        if (arguments.callee.done) return;
        arguments.callee.done = true;

        if (this._timer)  clearInterval(this._timer);

        this._readyCallbacks.each(function(f) { f() });
        this._readyCallbacks = null;
        this._loaded = true;
    },

    onDOMReady : function(f) {
        if (this._loaded) {
            f();
            return ;
        }
        if (!this._readyCallbacks) {
            var domReady = this._domReady.bind(this);

            if (document.addEventListener)
                document.addEventListener("DOMContentLoaded", domReady, false);

            /*@cc_on @*/
            /*@if (@_win32)
              document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
              document.getElementById("__ie_onload").onreadystatechange = function() {
              if (this.readyState == "complete") domReady();
              };
              /*@end @*/

            if (/WebKit/i.test(navigator.userAgent)) {
                this._timer = setInterval(function() {
                    if (/loaded|complete/.test(document.readyState)) domReady();
                }, 10);
            }

            Event.observe(window, 'load', domReady);
            Event._readyCallbacks =  [];
        }
        Event._readyCallbacks.push(f);
    }
});

Element.addMethods(
{
    update: function(element, html) {
        html = typeof html == 'undefined' ? '' : html.toString();
        $(element).innerHTML = html.stripScripts();
        setTimeout(function() {
            html.evalScripts();
            try {
                Mxmfo.history.ajaxify(element);
            } catch (e) {
            }
        }, 10);
        return element;
    },

    replace: function(element, html) {
        element = $(element);
        html = typeof html == 'undefined' ? '' : html.toString();
        if (element.outerHTML) {
            element.outerHTML = html.stripScripts();
        } else {
            var range = element.ownerDocument.createRange();
            range.selectNodeContents(element);
            element.parentNode.replaceChild(
                                            range.createContextualFragment(html.stripScripts()), element);
        }
        setTimeout(function() {
            html.evalScripts();
            try {
                Mxmfo.history.ajaxify(element);
            } catch (e) {
            }
        }, 10);

        return element;
    }
});

function MyHistory()
{
    this.defaultLocation = null;
    this.initLoading();

    /* history support */
    dhtmlHistory.initialize();
    dhtmlHistory.addListener(this.historyChange.bind(this));

    // determine what our initial location is
    // by retrieving it from the browser's
    // location after the hash
    currentLocation = dhtmlHistory.getCurrentLocation();
    if (currentLocation == '') {
        var url = String(document.location);
        this.defaultLocation = this.getHashFromUrl(url);
        historyStorage.put(this.defaultLocation, url + '::');
    }

    // ajax
    Ajax.Responders.register({
        onLoading: function() {
            Ajax.loading_cnt++;
            Ajax.loading_div.show();
        }
    });
    this.ajaxify(document);
}

MyHistory.prototype.initLoading = function()
{
    Ajax.clicked_obj = null;
    Ajax.loading_cnt = 0;
    Ajax.loading_div = $('loading');
    Event.observe(document, 'scroll', this.scrollLoading.bindAsEventListener(this));
}

MyHistory.prototype.scrollLoading = function(event)
{
    res = document.documentElement.scrollTop || document.body.scrollTop;
    Ajax.loading_div.setStyle({top: res + 'px'});
}

MyHistory.prototype.ajaxCallback = function(XHR, eJSON)
{
    try {
        eval(eJSON);
    } catch (e) {
    }
    if (Ajax.clicked_obj && Ajax.clicked_obj.submited) {
        Ajax.clicked_obj.submited = false;
    }
    if (Ajax.loading_cnt > 0) {
        Ajax.loading_cnt--;
    }
    if (Ajax.loading_cnt == 0) {
        Ajax.loading_div.hide();
    }
}

MyHistory.prototype.ajaxify = function(root)
{
    root = $(root);

    /* parse links */
    current = root.getElementsByTagName('a');
    curLen = current.length;
    for (j = 0; j < curLen; j++) {
        if (current[j].name != 'ajax') {
            continue;
        }

        if (typeof(current[j].alreadyObserved) == 'undefined') {
            current[j].alreadyObserved = true;
            current[j].observe('click',
                               this.click.bindAsEventListener(this, current[j]));
        }
    }

    /* parse forms */
    current = root.getElementsByTagName('input');
    curLen = current.length;
    for (j = 0; j < curLen; j++) {
        if (current[j].name != 'ajax' || !current[j].form) {
            continue;
        }

        this.addAjaxForm(current[j].form);
    }

    if (Ajax.loading_cnt == 0) {
        Ajax.loading_div.hide();
    }
}

MyHistory.prototype.addAjaxForm = function(form)
{
    form = $(form);
    form.submitForm = this.submitForm.bind(this, form);
    form.observe('submit', this.checkFormSubmit.bindAsEventListener(this, form));
    if (!form.getInputs('submit').length) {
        inputs = form.getInputs();
        for (i = 0; i < inputs.length; i++) {
            if (inputs[i].type != 'password' && inputs[i].type != 'text') {
                continue;
            }
            inputs[i].observe('keyup',
                              this.checkFormSubmit.bindAsEventListener(this, form));
        }
    }
}

MyHistory.prototype.click = function(e, node)
{
    Ajax.clicked_obj = $(node);
    this.request(Ajax.clicked_obj.href, Ajax.clicked_obj.hasClassName('no_history'));
    Event.stop(e);
}

MyHistory.prototype.request = function(url, noHistory)
{
    var pars = '';
    if (!noHistory) {
        dhtmlHistory.add(this.getHashFromUrl(url), url + '::' + pars);
    }

    var myAjax = new Ajax.Request(url,
        {
            method: 'get',
            parameters: pars,
            onComplete: this.ajaxCallback.bind(this)
        });
}

MyHistory.prototype.submitForm = function(form)
{
    form = $(form);
    form.submited = true;
    Ajax.clicked_obj = form;
    form.request({
        onComplete: this.ajaxCallback.bind(this)
    });
}

MyHistory.prototype.checkFormSubmit = function(e, form)
{
    Event.stop(e);
    form = $(form);

    if ((!e.keyCode || e.keyCode == Event.KEY_RETURN) && !form.submited) {
        this.submitForm(form);
    }
}

MyHistory.prototype.displayLocation = function(historyData)
{
    if (!historyData) {
        if (!this.defaultLocation) {
            var hash = String(document.location).split('#')[1];
            if (!hash || !hash.length) {
                return ;
            }
            historyData = historyStorage.get(hash);
        } else {
            historyData = historyStorage.get(this.defaultLocation);
        }
    }

    if (historyData) {
        var a = historyData.split('::');
        var myAjax = new Ajax.Request(a[0],
            {
                method: 'get',
                parameters: a[1],
                onComplete: this.ajaxCallback.bind(this)
            }
                                      );
    }
}

MyHistory.prototype.getHashFromUrl = function(url)
{
    return (MD5Hash.hex_md5(url));
}

MyHistory.prototype.historyChange = function(newLocation, historyData)
{
    if (newLocation.length != 32) {
        return;
    }
    this.displayLocation(historyData);
}

var Bigini = {
    history: null,
    eval_data: null,

    init: function() {
        Bigini.history = new MyHistory();
        if (Bigini.eval_data) {
            try {
                eval(Bigini.eval_data);
            } catch (e) {
            }
        }
    }
}

Event.onDOMReady(function() {
    Bigini.init();
});
