/*
    http://www.JSON.org/json2.js
    2009-04-16

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html
*/

/*jslint evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/

// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (!this.JSON) {
    JSON = {};
}
(function () {

    function f(n) {
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };

        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }

    var cx = new RegExp('[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]', 'g');
    var escapable = new RegExp('[\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]', 'g');
    var gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

        escapable.lastIndex = 0;
        return escapable.test(string) ?
            '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
    }


    function str(key, holder) {

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            //value = value.toJSON(key); // get double quoting with prototypejs
        }

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

            return String(value);

        case 'object':

            if (!value) {
                return 'null';
            }

            gap += indent;
            partial = [];

            if (Object.prototype.toString.apply(value) === '[object Array]') {

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

                v = partial.length === 0 ? '[]' :
                    gap ? '[\n' + gap +
                            partial.join(',\n' + gap) + '\n' +
                                mind + ']' :
                          '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

            v = partial.length === 0 ? '{}' :
                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                        mind + '}' : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

            var i;
            gap = '';
            indent = '';

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

            } else if (typeof space === 'string') {
                indent = space;
            }

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

            return str('', {'': value});
        };
    }


    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

            var j;

            function walk(holder, key) {

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

                j = eval('(' + text + ')');

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

            throw new SyntaxError('JSON.parse');
        };
    }
}());

// mail.ru specific code

var ajax_requests = [];
var ajaxHandleStateChange = function() {
    for(var k = 0; k<ajax_requests.length; k++) {
        if (ajax_requests[k].request == null) {
            ajax_requests.splice(k--,1);
            continue;
        }
        if (ajax_requests[k].request.readyState == 4) {
            var request = ajax_requests[k];
            ajax_requests.splice(k--,1);
            try {
                request.ready();
            } catch (e) {}
            continue;
        }
    }
}

function GetAjaxRequest() {
    var request = null;
    // branch for native XMLHttpRequest object
    if (typeof XMLHttpRequest != "undefined") {
        try {
            request = new XMLHttpRequest();
        } catch(e) {
            request = null;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) {
        try {
            request = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
                try {
                request = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch(e) {
                  request = null;
                }
        }
    }
    return request;
}

function AjaxRequest(method, script_name, func_name, args, callback, callback_object) {
    this.method = method;
    this.callback = callback;
    this.callback_object = callback_object;
    this.args = args;
    this.url = script_name + '?ajax_call=1&func_name=' + escapePlus(func_name) + '&back=' + escapePlus(window.location) + '&data=' + escapePlus(JSON.stringify(this.args));
}

AjaxRequest.prototype = {
    send : function() {
        var request = GetAjaxRequest();
        if (request) {
            this.request = request;
            request.onreadystatechange = ajaxHandleStateChange;
            if (this.method == "POST") {
                var idx=this.url.indexOf('?');
                var post = this.url.substr(idx+1);
                var url = this.url.substr(0,idx);
                request.open("POST", url, true);
                request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                request.send(post);
            } else {
                request.open("GET", this.url, true);
                request.send(null);
            }
            return true;
        } else {
            return false;
        }
    },
    ready : function() {
        if (this.request.status != 200) return;
        var data = eval(this.request.responseText);
        var magick = data.shift();
        if (magick != MagickString) return;
        var result = data.shift();
        if (result != OKCommand && result != RedirectCommand) return;
        if (result == OKCommand) {
            if (this.callback) {
                this.callback.apply(this.callback_object?this.callback_object:window,data);
            }
        } else if (result == RedirectCommand) {
            redirect.apply(window,data);
        }
        return;
    }
}

function redirect(url) {
    window.location=url;
}

function escapePlus(param) {
    param = escape(param);
    return String(param).replace(/\+/g,'%2B');
}

function escapeParam(param) {
    return String(param).replace(/\\/g, '\\\\').replace(/&/g, '\\&');
}

function unescapeParam(param) {
    return String(param).replace(/\\\\&/g, '&').replace(/\\\\/g, '\\');
}

function splitParam(param) {
    if(param == "") return new Array();
    var params = unescapeParam(param).split('&');
    for(var i = 0; i<params.length; i++) {
        if(params[i].substr(params[i].length-1,1) == '\\' && params.length>i+1) {
            params.splice(i, 2, params[i]+'&'+params[i+1]);
            i--;
        }
    }
    for(var i = 0; i<params.length; i++)
        params[i]=params[i].substr(1,params[i].length-2);
    return params;
}
