
Util = {};

/** константы **/
Util.__regexpProto = "(ht|f)t(p|ps)";
Util.__regexpSymbols = "[^\\s\\.?/]";
Util.__regexpAfterDomainDelimeter = "[?/]";
Util.__regexpAllText = "\\S";
Util.__regexpPort = ":\\d{1,5}";
Util.__regexpAllTextWithoutDot = "[^ \\f\\n\\r\\t\\v\\.]";
Util.__URL_REGEXP = new RegExp("(" + 
				Util.__regexpProto + "://" +
				Util.__regexpSymbols+"*" + "\\." + "(" + Util.__regexpSymbols + "*\\.)*" + Util.__regexpSymbols+"{2,4}" + "(" + Util.__regexpPort + "){0,1}" +
				"(" + Util.__regexpAfterDomainDelimeter + "(" + Util.__regexpAllText+"*" + Util.__regexpAllTextWithoutDot + ")*" + ")*" +
			")", "ig");

Util.__regexpEmailText = "[a-zA-Z\\d\\u005F\\u002D]+[\\u005F\\u002E\\u002Da-zA-Z\\d]*";
Util.__regexpEmailDomain = "([A-Za-z]{2,4})";
Util.__EMAIL_REGEXP = new RegExp("(" + Util.__regexpEmailText + "@" + Util.__regexpEmailText + "\\u002E" + Util.__regexpEmailDomain + ")", "ig");

/* Some Array class enhancements. */
Array.prototype.remove = function(n){
    this.splice(n,1);
/*
    for (var i=n; i<this.length-1; i++){
        this[i] = this[i+1];
    }
    this.length = this.length-1;
    */
};

/* Some String class enhancements. */

/*
 * Defines if string starts with specified string <code>str</code>.
 *
 *    @param str String to compare with
 *    @return <code>true</code> if original string starts with <code>str</code>; 
 *      <code>false</code> otherwise
 */
String.prototype.starts_with = function( str ) {
  return (this.indexOf( str ) == 0);
};

Util.trim = function(s) {
    if(!s)
        return '';
    return s.replace(/(^\s+)|(^\u00A0+)|(^\u00A0+)|(\s+$)/g, ''); 
};

Util.isEmpty = function(s) {
    if(s == null || typeof(s) == "undefined")
        return true;
    if(s instanceof Array)
        return s.length == 0;
    if(typeof(s) == "string")
        return Util.trim(s).length == 0;
    return false;
};

/**
 * Не совсем стандартный strcmp
 * возвращает номер символа в котором различие, затем величину различия
 */
Util.strcmp = function(a, b){
    for (var i=0; i<a.length && i<b.length; i++){
    	var ai = a.charCodeAt(i);
    	var bi = b.charCodeAt(i);
        if (ai != bi)
            return {index: i, delta: ai - bi};
    }
    if (a.length == b.length)
        return {index: 0, delta: 0};
    if (a.length>b.length)
    	return {index: b.length, delta: a.charCodeAt(b.length)};
	else
		return {index: a.length, delta: -b.charCodeAt(a.length)};
/*    if (a < b)
        return -1;
    else if (a == b)
        return 0;
    else 
        return 1;*/
};

/**
 * Дубликат в Util.java
 */

Util.smileTable = {
    ':)' : '/img/smile01.gif',
    ':-)' : '/img/smile01.gif',
    ':(' : '/img/smile02.gif',
    ':-(' : '/img/smile02.gif',
    ':-D' : '/img/smile03.gif',
    ':-P' : '/img/smile04.gif',
    '8-)' : '/img/smile05.gif',
    ':\'(' : '/img/smile06.gif',
    ':-X' : '/img/smile07.gif',
    ':-|' : '/img/smile08.gif',
    ':-!' : '/img/smile09.gif'
};

Util.plainToHtml = function(s) {
//    var regexp = /<(br|BR)\s*[/]{0,1}>|[<>&"\'"\n\r]/g;
	var regexp = new RegExp("<(br|BR)\\s*[/]{0,1}>|[<>&\"\\'\"\n\r]", "g");
    return s ? s.replace(regexp, Util._plainToHtml) : '';
};


Util._plainToHtml = function(match){
    if (match=="<")
        return "&lt;"
    else if (match==">")
        return "&gt;"
    else if (match=="\"")
        return "&quot;"
    else if (match=="'")
        return "&#039;"
    else if (match=="&")
        return "&amp;"
    else if (match=="\n")
        return "<br/>";
    else return " ";
};

Util.__location = null;
Util.domain = function(){
	if (Util.__location == null)
		Util.__location = window.location + '';
	
	var loc = ''+Util.__location;
	if (loc.indexOf('http://') == 0)
		loc = loc.substring('http://'.length);
	else if (loc.indexOf('https://') == 0)
		loc = loc.substring('https://'.length);
	if (loc.indexOf('www.') == 0)
		loc = loc.substring('www.'.length);
	var i1 = loc.indexOf('/');
	var i2 = loc.indexOf('?');
	var i = -1;
	if (i2 >= 0 && i2 < i1)
		i = i2;
	else if (i1 >= 0)
		i = i1;
	if (i >= 0)
		loc = loc.substring(0, i);
	return loc;
};

Util.replaceAll = function(s, from, to){
	return s.replace(new RegExp(from, "g"), to);
};

Util.unquote = function(s){
	s = Util.replaceAll(s, '&quot;', '"');
	s = Util.replaceAll(s, '&lt;', '<');
	s = Util.replaceAll(s, '&gt;', '>');
	s = Util.replaceAll(s, '&amp;', '&');
	s = Util.replaceAll(s, '\r', '');
	s = Util.replaceAll(s, '\n', '<br/>');
	return s;
};

Util.isChild = function(parent, child){
	for (; child.parentNode != null; child = child.parentNode){
		if (child.parentNode == parent)
			return true;
	}
	return false;
};


/**
  * node -узел от которого пойдет рекурсия
  * tagName - имя тега, который заменяется
  * nodeTestFunction - функция, возвращающая true/false в зависимости от того, подходит ли узел
  * replaceTagName - имя тег на который заменяется
  * replaceFunction которая по тегу выдает тектсовое содержимое нового тега
  **/
Util._nodeReplacer = function(node, tagName, nodeTestFunction, replaceTagName, replaceFunction){
	if (node){
		for (var i = 0; i < node.childNodes.length; i++){
			var ch = node.childNodes[i];
			if ((tagName == null || ch.tagName == tagName) && (nodeTestFunction == null || nodeTestFunction(ch))){
				var rpl = replaceFunction(ch);
				if (rpl != null){
					var span = document.createElement(replaceTagName);
					span.innerHTML = rpl;
					node.insertBefore(span, ch);
					node.removeChild(ch);
				}
			}
			else
				Util._nodeReplacer(ch, tagName, nodeTestFunction, replaceTagName, replaceFunction);
		}
	}
};

/**
  * подменяет теги с картинками-смайлами на их текстовые значения
  **/
Util._smileReplacer = function(node, replaceSmilesBy){
	Util._nodeReplacer(node, 'IMG', 
		function(ch){
			var src = ch.src;
			for (var smile in Util.smileTable){
				var smileSrc = Util.smileTable[smile]
				if (src.indexOf(smileSrc) == src.length-smileSrc.length)
					return true;
			}
			return false;
		},
		"SPAN",
		function(ch){
			if (replaceSmilesBy != null)
				return replaceSmilesBy;
			var src = ch.src;
			for (var smile in Util.smileTable){
				var smileSrc = Util.smileTable[smile]
				if (src.indexOf(smileSrc) == src.length-smileSrc.length)
					return smile;
			}
			return null;
		});
};

/**
  * подменяет <br> на \n
  **/
Util._brReplacer = function(node){
	Util._nodeReplacer(node, 'BR', null, "SPAN", function(){ return "\n" });
};

/**
 * подменяет <p>..</p>, <li>..</li>, <div>..</div> на \n и контент кроме первого
 **/
Util._p_li_div_Replacer = function(node){
	var replacer = function(n){
			var first = n.parentNode != null && n.parentNode.tagName == "BODY" && n.parentNode.firstChild == n;
			return (first ? "" : "<br/>") + n.innerHTML;
		};
	Util._nodeReplacer(node, 'P', null, "SPAN", replacer);
	Util._nodeReplacer(node, 'LI', null, "SPAN", replacer);
	Util._nodeReplacer(node, 'DIV', null, "SPAN", replacer);
};

/**
  * картинки-смайлы заменяет на их текст
  * replacesmiles по дефолту включен на их коды
  **/
Util.htmlToPlain = function(s, replaceSmilesBy){
	if (typeof(replaceSmiles) == 'undefiled')
		replaceSmiles = null;
	var tmp = document.createElement("BODY");
	tmp.innerHTML = s;
	// подменяет картинки со смайлами на спаны.
	Util._smileReplacer(tmp, replaceSmilesBy);
	Util._p_li_div_Replacer(tmp);
	return Util._htmlAsText(tmp);
	// думаю надо сделвть br аккуратными, удалить все кроме них, а потом взять innerHTML и пройтись replace
	//Util._brReplacer(tmp);
	//return $(tmp).text();
};

Util._htmlAsText = function(node){
	if (node == null)
		return "";
	else if (node.nodeType == 3 || node.nodeType == 4)
		//alert(['|'+node.nodeValue+'|', '|'+Util.trim(node.nodeValue)+'|', '|'+Util.trim(node.nodeValue + '')+'|', "||" , /^\s+$/g .test(node.nodeValue), /^\s+$/g .test(' '), node.nodeValue.charCodeAt(0)]);
		return Util.trim(node.nodeValue);
	else if (node.nodeType == 1){
		if (node.tagName == 'BR')
			return '\n';
		else{
			var x = "";
			for (var i=0; i<node.childNodes.length; i++)
				x += Util._htmlAsText(node.childNodes[i]);
			return x;
		}
	}
};

/**
  * заменит все что похоже на текст ссылки на ссылку
  **/
Util.markAnchors = function(s){
 	return s.replace(Util.__URL_REGEXP, '<a href="$1" target="_blank">$1</a>');
};

Util.markEmails = function(s){
 	return s.replace(Util.__EMAIL_REGEXP, '<a href="mailto:$1">$1</a>');
};

Util.replaceSmileysToImages = function(s){
	var before;
	for (var smile in Util.smileTable){
		do {
			before = s;
			s = s.replace(smile, "<img class=\"in-text-smile\" src=\""+Util.smileTable[smile]+"\"/>");
		} while (s != before);
	}
	return s;
};

Util.preloadImage = function(url){
	var img = new Image();
	img.src = url;
};

Util.escapeJquery = function(s){
	return s.replace(/:/g,"\\:").replace(/\./g,"\\.").replace(/\*/g,"\\*").replace(/\-/g,"\\-");
};

Util.isNumberString = function(str){
	return /^\d+$/.test(Util.trim(str));
};

Util.splitLongWords = function(str){
	/*var count = 0;
	var res = '';
	for (var i=0; i<str.length; i++){
		var c = str.charAt(i);
		var code = str.charCodeAt(i);
		if (c == '\r' || c == ' ' || c == '\t' || c == '\n' || code == 160 || code == 173)
			count = 0;
		else if (count > 20){
			count = 0;
			res += String.fromCharCode(8203);//String.fromCharCode(173); // символ невидимого пробела
		}
		else
			count++;
		res += c;
	}
	return res;*/
	return str;
};


Util.escapeHtml = function(text){
	return $("<div/>", { text: text }).html();
};