(function(){
    
    /*
        USAGE:
            var req = new Social.DataRequest( widget.getAuth() );
            req.add( req.Get.Person(id), "key" );
        OR, LATER:
            var req = new Social.DataRequest( widget.getAuth(), "OpenSocial" );
            req.add( req.newFetchPersonRequest(id), "key" );
    */

    function undef(param) { return param };
  
    Social.DataRequest = function(authToken,wrapper){
        if (wrapper == undef()) wrapper = "Common";
        this.queue = [];
        this.authToken = authToken;
        Social.DataRequest[wrapper](this);
    };

    Social.DataRequest._gatewayUrl = "/social";
    
    Social.DataRequest._nextId = 0;
    Social.DataRequest.NextId = function()
    { 
        Social.DataRequest._nextId++;
        return "_autoid_"+Social.DataRequest._nextId;
    }

    Social.DataRequest.WrapCreate = function(result)
    {
        if (typeof(result) == typeof({}))
            if (result["@create"] != undef())
                eval("result = new "+result["@create"]+"(result);");
            else
                for (var i in result)
                    result[i] = Social.DataRequest.WrapCreate(result[i]);
        else
            if (typeof(result) == typeof([]))
                for(var i=0; i<result.length; i++)
                    result[i] = Social.DataRequest.WrapCreate( result[i] );
        return result;
    };
    
    Social.DataRequest.Common = function(datarequest)
    {
        var prefix = "social.";
        var t;
        for (var x in Social.DataRequest.Common.methods)
        {
            datarequest[x] = { _ : datarequest };
            for( var y in Social.DataRequest.Common.methods[x] )
                if (typeof(y) == typeof(""))
                    datarequest[x][y] =  eval("t = function( params ) { return this._._add('"+prefix+x+y+"', arguments, Social.DataRequest.Common.methods, '"+x+"', '"+y+"'); }");
        }
        return datarequest;
    }
    Social.DataRequest.Common.methods = 
    {
        "Get" : {   
            "Person"  : ["ids"], 
            "Friends" : ["ids"],
            "AppData" : ["title"] 
                },
        "Set" : {
            "AppData" : ["title", "value"]
                },
        "Notify" : {
            "App"    : ["ids","title","href","options"],
            "Action" : ["ids","title","href","options"] // options : {subject, body, action, href_action}
                }
    }
    
    Social.DataRequest.prototype = {
        _add : function( method, parameters, definitions, x,y )
        {
            var result = { "request" : method, "params" : {} };
            for (var i=0; i<definitions[x][y].length; i++)
                result["params"][ definitions[x][y][i] ] = parameters[i];
            return result;
        },

        // public methods --------------------------------
        add : function( req, key ) // req -- это { request, params }
        {
            if (key != undef()) req.key = key;
            if (req.key == undef()) req.key = Social.DataRequest.NextId();
            this.queue[ this.queue.length ] = req;
        },
        send : function( handler )
        {
            this.handler = handler;
            y5.Post.XML(  Social.DataRequest._gatewayUrl, {
                    onload : function(r) { 
                        var responses = eval( r.responseText.replace( /^.*@@@start@@@/, "").replace( /@@@end@@@.*$/, "") );
                        var results = {};
                        for (var i=0; i<responses.length; i++)
                            results[responses[i].key] = Social.DataRequest.WrapCreate(responses[i].result)
                        handler(results,status,responses);
                    }},
                {   request : y5.JSON.toString(this.queue),
                    auth : this.authToken
                }
                );
        }
    };
    
    Social.DataRequest.Exception = function(data)
    {
        this.prototype = Social.DataRequest.Exception;
        this._data = data;
        this.type = data.type;
        this.msg  = data.msg;
    }

})();
