/* 
 * Вспомогательные функции
 */


// извлекает по маске значение из имени css-класса конкретного элемента jQuery
function getValueFromClassName(wildCard, jEl) {
	var classNames=jEl.attr("class").split(" ");
	for(var i=0;i<classNames.length;i++) {
		if(classNames[i].indexOf(wildCard)!=-1) {
			return $.trim(classNames[i].replace(wildCard,""));
		}
	}
	return 0;
}

// включает подсказку в текстовом поле
jQuery.fn.hintOnEmpty=function(hint){
    return this.each(function(){
        var me=$(this);

        me.bind("truevalue", function(){
            if($(this).val()==hint) {
                $(this).removeClass("empty").val("");
            }
        }).bind("hintvalue", function(){
            if($(this).val()=="") {
                $(this).addClass("empty").val(hint);
            }
        });

        me.focus(function(){
            me.trigger("truevalue");
        }).blur(function(){
            me.trigger("hintvalue");
        });

        me.trigger("hintvalue");
    });
};


// склонение счетных существительных
function getPlural(number, nomSingular, genSingular, genPlural) {
	var n=parseInt(number);
	switch(true) {
		 case (n % 10 == 1 && n % 100 != 11):
			 return nomSingular;
			 break;
		 case (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)):
			 return genSingular;
			 break;
		 default:
			 return genPlural;
	}
}

/**
 * Отдает опции для контрола select
 * @param Object data 
 * @return array
 */
function getOptionList(data, value, name) {
	var result='';
	var count=0;

	if(data.length && name && value) {
		// если передан массив объектов
		for(var i=0, j=data.length; i<j; i++) {
			result+='<option value="' + data[i][value] + '">' + data[i][name] + '</option>';
			count++;
		}
	} else {
		// если передан ассоциативный массив
		for(key in data) {
			result+='<option value="' + key + '">' + data[key] + '</option>';
			count++;
		}
	}

	if(count>1) {
		result='<option value="no">выбрать</option>' + result;
	}

	return result;
}

/**
 * Фильтрация ассоциативного массива массивом айдишников
 * @param Object valueArray
 * @param Array filterArray
 * @return Object result
 */
function filterArrayByIds(valueArray, ids){
	var result={};

	for(var i=0, j=ids.length; i<j; i++) {
		if(valueArray[ids[i]]) {
			result[ids[i]]=valueArray[ids[i]];
		}
	}
	return result;
}

/**
 * Получение html-кода элемента включая сам элемент
 */
jQuery.fn.extend({
	htmlOuter: function() {
		return $('<div>').append(this.clone()).remove().html();
	}
});

/**
 * Jquery ui Автокомплит на основе селекта
 */
(function( $ ) {
	$.widget( 'ui.combobox', {
		options: {
			inputText: '',
			urlItem: '',
			urlEmpty: '',
			aliases: ''
		},
		_create: function() {
			var self = this,
				select = this.element.hide(),
				selected = select.children( ':selected' ),
				value = selected.val() ? selected.text() : '';
			var input = this.input = $( '<input>' )
				.insertAfter( select )
				.val( value )
				.autocomplete({
					delay: 0,
					minLength: 2,
					source: function( request, response ) {
						var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), 'i' );
						response( select.children( 'option' ).map(function() {
							var text = $( this ).text();
							
							var aliasCheck = 0;
							
							if( self.options.aliases[text] ) 
							{
								for(var i=0; i<self.options.aliases[text].length; i++)
								{
									if(matcher.test( self.options.aliases[text][i] )) {aliasCheck = 1; break;}
								}
							}

							if ( this.value && ( !request.term || matcher.test(text) || aliasCheck ) )
								return {
									label: text.replace(
										new RegExp(
											'(?![^&;]+;)(?!<[^<>]*)(' +
											$.ui.autocomplete.escapeRegex(request.term) +
											')(?![^<>]*>)(?![^&;]+;)', 'gi'
										), '<strong>$1</strong>' ),
									value: text,
									option: this
								};
						}) );
					},
					select: function( event, ui ) {
						ui.item.option.selected = true;
						self._trigger( 'selected', event, {
							item: ui.item.option
						});
						if(self.options.urlItem) window.location=self.options.urlItem+ui.item.option.value;
					}
				})
				.focus( function() { if(this.value==self.options.inputText) this.value=''; } )
				.blur( function() { if(this.value=='') this.value=self.options.inputText; } )
				.keyup(function(event) {  if (event.keyCode == '13' && this.value=='' && self.options.urlEmpty) window.location=self.options.urlEmpty;  } );
				//.addClass( 'ui-widget ui-widget-content ui-corner-left' );

			input.data( 'autocomplete' )._renderItem = function( ul, item ) {
				return $( '<li></li>' )
					.data( 'item.autocomplete', item )
					.append( '<a>' + item.label + '</a>' )
					.appendTo( ul );
			};
		},

		destroy: function() {
			this.input.remove();
			this.element.show();
			$.Widget.prototype.destroy.call( this );
		}
	});
})( jQuery );


/**
 * преобразование даты в читаемый вид
 *
 * @param object date объект типа Date
 * @param string monthCase в каком падеже выводить месяцы ("nom" - именительный, "gen" - родительный)
 * @return string в формате "23 февраля 2010 года"
 */
function getHumanDate(date, monthCase)
{
	date = date || 'now';
	monthCase = monthCase || 'gen';
	
	if(!(date instanceof Date)) {
		date = new Date();
	}
	
	months = {
		'nom'	: [
			'январь',
			'февраль',
			'март',
			'апрель',
			'май',
			'июнь',
			'июль',
			'август',
			'сентябрь',
			'октябрь',
			'ноябрь',
			'декабрь'
		],
		'gen'	: [
			'января',
			'февраля',
			'марта',
			'апреля',
			'мая',
			'июня',
			'июля',
			'августа',
			'сентября',
			'октября',
			'ноября',
			'декабря'
		]
	};

	day   = date.getDate();
	month = months[monthCase][date.getMonth()];
	year  = date.getFullYear();

	return day+' '+month+' '+year+' года';
}

// сериализация JavaScript-объекта
function serializeObject(obj, re) {
	var result = [];
	$.each(obj, function(i, val) {
		if ((re && re.test(i)) || !re)
			result.push(i + ': ' + (typeof val == 'object' ? val.join
				? '\'' + val.join(', ') + '\'' : serializeObject(val) : '\'' + val + '\''));
	});
	return '{' + result.join(', ') + '}';
};

function utf8_encode ( str_data ) {	// Encodes an ISO-8859-1 string to UTF-8

	str_data = str_data.replace(/\r\n/g,"\n");
	var utftext = "";

	for (var n = 0; n < str_data.length; n++) {
		var c = str_data.charCodeAt(n);
		if (c < 128) {
			utftext += String.fromCharCode(c);
		} else if((c > 127) && (c < 2048)) {
			utftext += String.fromCharCode((c >> 6) | 192);
			utftext += String.fromCharCode((c & 63) | 128);
		} else {
			utftext += String.fromCharCode((c >> 12) | 224);
			utftext += String.fromCharCode(((c >> 6) & 63) | 128);
			utftext += String.fromCharCode((c & 63) | 128);
		}
	}

	return utftext;
}


function md5 ( str ) {	// Calculate the md5 hash of a string

	var RotateLeft = function(lValue, iShiftBits) {
			return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
		};

	var AddUnsigned = function(lX,lY) {
			var lX4,lY4,lX8,lY8,lResult;
			lX8 = (lX & 0x80000000);
			lY8 = (lY & 0x80000000);
			lX4 = (lX & 0x40000000);
			lY4 = (lY & 0x40000000);
			lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
			if (lX4 & lY4) {
				return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
			}
			if (lX4 | lY4) {
				if (lResult & 0x40000000) {
					return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
				} else {
					return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
				}
			} else {
				return (lResult ^ lX8 ^ lY8);
			}
		};

	var F = function(x,y,z) { return (x & y) | ((~x) & z); };
	var G = function(x,y,z) { return (x & z) | (y & (~z)); };
	var H = function(x,y,z) { return (x ^ y ^ z); };
	var I = function(x,y,z) { return (y ^ (x | (~z))); };

	var FF = function(a,b,c,d,x,s,ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		};

	var GG = function(a,b,c,d,x,s,ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		};

	var HH = function(a,b,c,d,x,s,ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		};

	var II = function(a,b,c,d,x,s,ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		};

	var ConvertToWordArray = function(str) {
			var lWordCount;
			var lMessageLength = str.length;
			var lNumberOfWords_temp1=lMessageLength + 8;
			var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
			var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
			var lWordArray=Array(lNumberOfWords-1);
			var lBytePosition = 0;
			var lByteCount = 0;
			while ( lByteCount < lMessageLength ) {
				lWordCount = (lByteCount-(lByteCount % 4))/4;
				lBytePosition = (lByteCount % 4)*8;
				lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount)<<lBytePosition));
				lByteCount++;
			}
			lWordCount = (lByteCount-(lByteCount % 4))/4;
			lBytePosition = (lByteCount % 4)*8;
			lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
			lWordArray[lNumberOfWords-2] = lMessageLength<<3;
			lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
			return lWordArray;
		};

	var WordToHex = function(lValue) {
			var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
			for (lCount = 0;lCount<=3;lCount++) {
				lByte = (lValue>>>(lCount*8)) & 255;
				WordToHexValue_temp = "0" + lByte.toString(16);
				WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
			}
			return WordToHexValue;
		};

	var x=Array();
	var k,AA,BB,CC,DD,a,b,c,d;
	var S11=7, S12=12, S13=17, S14=22;
	var S21=5, S22=9 , S23=14, S24=20;
	var S31=4, S32=11, S33=16, S34=23;
	var S41=6, S42=10, S43=15, S44=21;

	str = this.utf8_encode(str);
	x = ConvertToWordArray(str);
	a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;

	for (k=0;k<x.length;k+=16) {
		AA=a; BB=b; CC=c; DD=d;
		a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
		d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
		c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
		b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
		a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
		d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
		c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
		b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
		a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
		d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
		c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
		b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
		a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
		d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
		c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
		b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
		a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
		d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
		c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
		b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
		a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
		d=GG(d,a,b,c,x[k+10],S22,0x2441453);
		c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
		b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
		a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
		d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
		c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
		b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
		a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
		d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
		c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
		b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
		a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
		d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
		c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
		b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
		a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
		d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
		c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
		b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
		a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
		d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
		c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
		b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
		a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
		d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
		c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
		b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
		a=II(a,b,c,d,x[k+0], S41,0xF4292244);
		d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
		c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
		b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
		a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
		d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
		c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
		b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
		a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
		d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
		c=II(c,d,a,b,x[k+6], S43,0xA3014314);
		b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
		a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
		d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
		c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
		b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
		a=AddUnsigned(a,AA);
		b=AddUnsigned(b,BB);
		c=AddUnsigned(c,CC);
		d=AddUnsigned(d,DD);
	}

	var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);

	return temp.toLowerCase();
}
 
//javascript print_r
function print_r(arr, level) {
	var print_red_text = "";
	if(!level) level = 0;
	var level_padding = "";
	for(var j=0; j<level+1; j++) level_padding += "    ";
	if(typeof(arr) == 'object') {
		for(var item in arr) {
			var value = arr[item];
			if(typeof(value) == 'object') {
				print_red_text += level_padding + "'" + item + "' :\n";
				print_red_text += print_r(value,level+1);
		} 
			else 
				print_red_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
		}
	} 

	else print_red_text = "===>"+arr+"<===("+typeof(arr)+")";
	return print_red_text;
}
