(function ($) {

/**
 * Transform query string to object representation
 * @param string str string to transform
 * @param bool[optional] isUrl whether string presents whole url and it only part after '?' must be used
 * @return Object
 */
$.unquery = function (str, isUrl) {
    var res = {};
    // leave only part after '?' if correpsonding parameter is set
    if (isUrl) { 
        var ind = str.indexOf('?');
        if (ind >= 0) {
            str = str.substr(ind + 1);
        }
    }
    var parts = str.split('&');
    for (var i = 0; i < parts.length; i++) {
        var nv = parts[i].split('=');
        res[nv[0]] = unescape(nv[1].replace(/\+/g, ' ')) || null;
    }
    return res;
};

Function.prototype.sequence = function(fcn, scope){
    if(typeof fcn != "function"){
        return this;
    }
    var method = this;
    return function() {
        var retval = method.apply(this || window, arguments);
        fcn.apply(scope || this || window, arguments);
        return retval;
    };
};

/**
 * Apply scope for some function when it called
 * @param {object} scope Object for setting function scope to
 * @return {Function}
 */
Function.prototype.callback = function () {
    var scope = arguments[0];
    var f = this;
    var args = new Array();
    for (i = 1; i < arguments.length; args.push(arguments[i++]));
    
    return function () {
        return f.apply(scope, args);
    }
};

/**
 * Set strict scope for the function regardless of where it will
 * be called
 * @param {object} scope Object for setting function scope to
 */
Function.prototype.scope = function (scope) {
    var f = this;
    
    return function () {
        return f.apply(scope, arguments);
    }
};

/**
 * Initialize a component guessing its type from
 * class attribute of its HTMLElement
 */
$.fn.component = function () {
    var classNames = this.attr("class").split(/ +/);
    for (var c in classNames) {
        if ($.fn[classNames[c]]) { // jQuery component constructor with such name is registered
            return this[classNames[c]]();
        }
    } 
}

/**
 * Component
 * @constructor jQuery
 */
$.widget('ui.Component', {
    /**
     * Class name
     */
    type: 'Component',
    
    init: function () {
        
    },

    /**
     * Mask the component
     */
    mask: function () {
/*
		this.element.children().height(this.element.children().height());
        this.element.children().html('<div class="preloader"></div>')
 */     
        this.element.addClass('loading');
    },
    
    /**
     * Unmask the component
     */
    unmask: function () {
        this.element.removeClass('loading');
    },
    
    /**
     * Reload component content requesting a new one
     * from the server
     * @param {object} params Request parameters 
     */
    reload: function (params, callback) {
        this.mask();
        
        var endAjax = this.unmask;
        if (callback) {
            endAjax = endAjax.sequence(callback);
        }
        //params['location'] = window.location;
        //FIXME; it's hack for correct moving progect to tochka.net portal
        if (location.host == 'tutatama.com') {
        	location.citybase = '';
        }

        this.element.load(location.langbase + location.citybase + '/ajax/' + this.type + '/' + this.element.attr("id") +'/', params || {}, endAjax.callback(this));
    },
    
    /**
     * String representation
     */
    toString: function () {
        return '[' + this.type +'] ' + this.element.attr("id");
    }
});

})(jQuery);