/**
 * spadar-api
 *
 * LICENSE
 *
 * This source file is subject to the MIT license that is bundled
 * with this package in the file MIT-LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://api.spadar.com/license
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to api@spadar.com so we can send you a copy immediately.
 *
 * @category   spadar-api
 * @package    spadar::Ajax
 * @copyright  Copyright (c) 2008-2009 Yury Ksenevich (http://api.spadar.com)
 * @license    http://api.spadar.com/license     MIT License
 */

var spadar = spadar || {};

(function($)
{
    spadar.ajax = spadar.ajax || 
    {
        extractJs: function(sResponseText, iTextStatus, oXmlHttpRequest, sSelector)
        {
            var aScripts = sResponseText.match(/<script(.|\s)*?\/script>/g);
            if (aScripts)
            {
                $(document.body).append(aScripts.join(''));
            }
        }, 
    
        Request: function()
        {
            this.clearUrl();
            this.clearPost();
        }, 
    
        getRequest: function()
        {
            spadar.ajax._oRequest = spadar.ajax._oRequest || (new spadar.ajax.Request());

            return spadar.ajax._oRequest;
        }, 

        /**
         * @param Function fCallback JSON processor takes 2 params: JSON object and status text
         * @param Object oOptions
         */
        getJson: function(fCallback, oOptions) 
        {
            var oInit = {
                url      : spadar.ajax.getRequest().getUri(), 
                dataType : 'json', 
                data     : spadar.ajax.getRequest().getPost(), 
                type     : 'POST', 
                success  : fCallback
                };

            if (oOptions)
            {
                oInit = $.extend(oInit, oOptions);
            }

            $.ajax(oInit);
        }
    }
    
    spadar.ajax.Request.prototype = 
    {
        url: function(aArgs)
        {
            this._object2var(aArgs, this._aUriArgs);
    
            return this;
        }, 

        clearUrl: function()
        {
            this._parseUri();
    
            return this;
        }, 

        post: function(aArgs)
        {
            this._object2var(aArgs, this._aPost);
    
            return this;
        }, 

        _object2var: function(oObject, oVar)
        {
            if ('string' == typeof oObject) // Parse GET formatted query
            {
                var aParams = oObject.split('&');

                for (var i = 0; i < aParams.length; i++)
                {
                    var aNameVal = aParams[i].split('=');

                    if ('undefined' != typeof(oVar[decodeURIComponent(aNameVal[0])]))
                    {
                        delete oVar[decodeURIComponent(aNameVal[0])];
                    }

                    if (1 != aNameVal.length)
                    {
                        var sName  = decodeURIComponent(aNameVal[0]);
                        var sIndex = sName;
                        var sVal   = decodeURIComponent(aNameVal[1]);

                        if (-1 != sName.match(/\[\]/g))
                        {
                            sIndex = sName.replace(/\[\]/g, '[' + Math.random() + ']');
                        }

                        oVar[sIndex] = {'name': sName, 'value': sVal};
                    }
                }
            }
            else if (oObject instanceof Array) // Parse jQuery serializeArray format
            {
                for (var i = 0; i < oObject.length; i++)
                {
                    if ('undefined' != typeof(oVar[oObject[i].name]))
                    {
                        delete oVar[oObject[i].name];
                    }

                    if (null != oObject[i].value)
                    {
                        var sIndex = oObject[i].name;

                        if (-1 != oObject[i].name.match(/\[\]/g))
                        {
                            sIndex = oObject[i].name.replace(/\[\]/g, '[' + Math.random() + ']');
                        }

                        oVar[sIndex] = {'name': oObject[i].name, 'value': oObject[i].value};
                    }
                }
            }
            else if (oObject instanceof Object) // Parse JSON object format
            {
                for (var i in oObject)
                {
                    if ('undefined' != typeof(oVar[i]))
                    {
                        delete oVar[i];
                    }

                    if (null != oObject[i])
                    {
                        oVar[i] = {'name': i, 'value': oObject[i]};
                    }
                }
            }

            return this;
        }, 
    
        clearPost: function()
        {
            this._aPost = {};
    
            return this;
        }, 

        getUri: function()
        {
            if (0 == this._aUriArgs.length)
            {
                var sUri = this._sUri;
                return sUri;
            }

            return this._sUri + '?' + this.args2string(this._aUriArgs);
        }, 

        args2string: function(aArgs)
        {
            var aReturn = [];
    
            for (var sArg in aArgs)
            {
                if (null == aArgs[sArg].value)
                {
                    aReturn.push(aArgs[sArg].name);
                }
                else
                {
                    aReturn.push(aArgs[sArg].name + '=' + encodeURIComponent(aArgs[sArg].value));
                }
            }

            return aReturn.join('&');
        }, 

        getPost: function()
        {
            var aReturn = [];

            for (var i in this._aPost)
            {
                aReturn.push({'name': this._aPost[i].name, 'value': this._aPost[i].value});
            }

            return aReturn;
        }, 
    
        _parseUri: function()
        {
            this._sUri  = document.location.pathname;
            var sQuery  = document.location.search;
            if (0 == sQuery.indexOf('?'))
            {
                sQuery = sQuery.slice(1, sQuery.length);
            }
            this._aUriArgs = {};
    
            var aArgs = sQuery.split('&');
            if (aArgs.length > 0)
            {
                for (var i = 0; i < aArgs.length; i++)
                {
                    var aArg = aArgs[i].split('=');

                   this._aUriArgs[aArg[0]] = {'name': aArg[0], 'value': aArg[1] || null};
                }
            }
        }
    };

    $.fn.loadWidget = function(sTarget, oCallback) 
    {
        var oRequest = spadar.ajax.getRequest();
        
        // Prepare URI:
        var sUri = oRequest.getUri();
        
        var aCallbacks   = this._aCallbacks ? this._aCallbacks : [];
        this._aCallbacks = [];

        if (!this._bNoJs)
        {
            aCallbacks.unshift(spadar.ajax.extractJs);
        }

        if (oCallback)
        {
            aCallbacks.push(oCallback);
        }
        
        var oLoadCallback = function(sResponseText, iTextStatus, oXmlHttpRequest) 
        {
            for (var i = 0; i < aCallbacks.length; i++)
            {
                aCallbacks[i].call(this, sResponseText, iTextStatus, oXmlHttpRequest, sTarget);
            }
        };

        this.load(
            sUri + ' ' + sTarget, 
            oRequest.getPost(), 
            oLoadCallback
            );
        
        return this;
    }

    $.fn.loading = function(domContents)
    {
        var oInner = $(domContents);
        if (domContents)
        {
            this._domLoadingContents = domContents;
        }
    
        this.each(function() {
            var sWidth  = $(this).width();
            var sHeight = $(this).height();
            var oDiv    = document.createElement('div');
            var oDom    = $(oDiv).addClass('loading')
	            .width(sWidth)
	            .height(sHeight)
	            .css('margin-right', '-' + sWidth + 'px')
	            .css('margin-bottom', '-' + sHeight + 'px')
	            .css('display', 'block')
	            .css('z-index', '1001')
	            .css('position', 'relative').hide().fadeTo(0, 0.5, function(){oDom.show();});

            $(oDom).prependTo(this).append(oInner);
	        });
	
	    return this;
	}

	$.fn.noJs = function()
	{
	    if (!this._bNoJs)
	    {
	        this._bNoJs = true;
	    }
	
	    return this;
	}

})(jQuery);