/*
 * jQuery Translate plugin
 *
 * Version: 1.1.6
 *
 * http://code.google.com/p/jquery-translate/
 *
 * Copyright (c) 2008 BalÃ¡zs EndrÃ©sz (balazs.endresz@gmail.com)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * This plugin uses the 'Google AJAX Language API' (http://code.google.com/apis/ajaxlanguage/)
 * You can read the terms of use at http://code.google.com/apis/ajaxlanguage/terms.html
 *
 */

;(function($){

	function $fn(){}
	function $isSet(a){
		return typeof a!='undefined';
	}
	function $isString(a){
		return typeof a=='string';
	}

	function copyEvents(from, to){
		var events;
		to.each(function(i){
			if(!(events=$.data(from[i], 'events')))
				return false;
			for(var type in events)
				for(var handler in events[type])
					$.event.add(this, type, events[type][handler], events[type][handler].data);
		});
	}

	function cut(t){
		var m1=/<(?![^<]*>)/.exec(t);
		if(!m1){//if no broken tag present
			var m2=/>\s*$/.exec(t);
			if(!m2){//if doesn't end with '>'
				var m3=/[\.\?\!;:](?![^\.\?\!;:]*[\.\?\!;:])/.exec(t);
				if(m3){//if broken sentence present
					var m4=/>(?![^>]*<)/.exec(t);
					if(m4){
						if(m3.index > m4.index){
							t=t.substring(0, m3.index+1);
						}else t=t.substring(0, m4.index+1);
					}else t=t.substring(0, m3.index+1);
				}else t=t;
			}else t=t;
		}else t=t.substring(0, m1.index);

		return t;
	}

	function translate(){
		return new translate.prototype.init();
	}

	translate.prototype={
		init: function(){
			return this;
		},

		processInit: function(){
			this.txtorig=[];
			this.jqt=[];
			this.tc='';
			var opt=this.opt;

			this.jq=this.jq.not('script, '+opt.not);

			if(opt.walk===true){
				this.jq=this.jq.add(this.jq.find('*').not('script, '+opt.not));//add all contents to jq
				if(opt.not.length){//filter out childnodes if has any:
					var omit=$(opt.not).get(0), hasChildNode=false;
					omit=omit ? omit.firstChild : null;
					while (omit){
						if(omit.nodeType==1){
							hasChildNode=true;
							break;
						}
						omit=omit.nextSibling;
					}
					if(hasChildNode)
						this.jq=this.jq.not($(opt.not).find('*'));
				}
			}

			this.split.jqt=[];
			this.split.txtorig=[];
			this.split.finalarr=[];
			this.split.num=0;
			this.nct={};
			this.nct.jqt=[];
			this.nct.txtorig=[];

			this.jql=this.jq.length;
			this.n=-1;
			return this.process();

		},

		process: function(){
			this.n++;
			var that=this, opt=this.opt, trtext='', hasTextNode=false, hasChildNode=false, el=this.jq[this.n], e, cont;

			if(this.n==this.jql){
				if(opt.translate!==false && (!opt.split || this.nn===true))
					this.translateInit();
				if(opt.split){//complete callback if split was set
					this.jqt=this.split.jqt; this.num=this.split.num;
					this.finalarr=this.split.finalarr; this.txtorig=this.split.txtorig;
					var from=(this.from.length<2 && this.detlang) ? this.detlang : this.from;
					this.opt.complete.call(this, this.jqo, $(this.jqt), this.finalarr, this.txtorig, from, this.to, this.opt, this.num);
				}
				if($isSet(opt.nct))//complete callback for nodesContText
					this.opt.complete.call(this, $(this.nct.jqt), this.nct.txtorig);
				if(opt.walk===false)
					return this.jqo;
				if(opt.returnAll===true)
					return $(this.jqt);
				else
					return this.jqo;
			}

			if(!el)
				return this.process();
			e=$(el);

			if($isString(opt.subject))
				trtext=e.attr(opt.subject) || '';
			else{
				if(opt.altAndVal && (el.tagName.toLowerCase()=='img' || el.tagName.toLowerCase()=='input')){
					if(el.tagName.toLowerCase()=='img')
						trtext=e.attr('alt') || '';
					else{
						var type=e.attr('type') || ''; type=type.toLowerCase();
						if(type=='text' || type=='button' || type=='submit')
							trtext=e.val() || '';
					}
				}else if(el.tagName.toLowerCase()=='textarea')
					trtext=e.val();
				else{
					cont=el.firstChild;
					//---check childNodes
					if(opt.walk!==true)
						hasChildNode=true;

					while(cont){
						if(cont.nodeType==1){
							hasChildNode=true;
							break;
						}
						cont=cont.nextSibling;
					}
					//----------------

					if(!hasChildNode)//if doesn't have any children (not text)
						trtext=e.text();
					else{
						if(opt.walk!==true)
							hasTextNode=true;
						cont=el.firstChild;

						//---check textNodes
						while (cont){
							if(cont.nodeType==3 && cont.nodeValue.match(/\S/) !== null){//textnodes with text
								if(cont.nodeValue.match(/<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)>/) !== null){
									if(cont.nodeValue.match(/(\S+(?=.*<))|(>(?=.*\S+))/) !== null){
										hasTextNode=true;
										break;
									}
								}else{
									hasTextNode=true;
									break;
								}
							}
							cont=cont.nextSibling;
						}
						//---------------

						if(hasTextNode){//remove child nodes from jq
							trtext=e.html().replace(/<script[^<]+<[^<]+>/,'');//removes scripts
							this.jq=this.jq.not(e.find('*'));
						}else
							trtext='';
					}
				}
			}

			if(!trtext)
				return this.process();
			this.nn=true;
			this.jqt.push(el);
			if(opt.comments===false)
				trtext=this.strip(trtext);
			this.txtorig.push(trtext);

			if(!opt.split || !(this.n%opt.split==0)){
				if($isSet(opt.nct)){
					this.nct.jqt.push(el);
					this.nct.txtorig.push(trtext);
					opt.each.call(this, this.jqt.length-1, el, trtext);
				}
				if(opt.async)
					setTimeout(function(){
						that.process();
					}, opt.async);
				else
					return this.process();
			}else{
				this.nn=false;
				if(opt.translate!==false)
					return this.translateInit();
			}

		},


		translateInit: function(){
			if($isString(this.txtorig)){
				this.tc='<div>'+this.txtorig+'</div>';
				this.string=true;
			}else{
				this.tc='<div>'+this.txtorig.join('</div><div>')+'</div>';
				this.string=false;
			}

			//this.tc = this.tc.replace(/\n/g, "<br>");
			this.tf='';
			this.l=this.tc.length;
			this.tt='';
			this.start=0;
			this.divs=0;
			this.finalarr=[];
			this.num=0;

			return this.translate();
		},


		translate: function(){
			if(this.stopped===true)
				return;
			var that=this;

			this.tt=cut( this.tc.substring(this.start, this.start*1+this.opt.limit) )
			this.start=this.start+this.tt.length;//set next start position

			//---------handle each callbacks as transl arrived----------
			var i=this.tf.length;
			while(this.tf.lastIndexOf('</div>',i)>-1){
				i=this.tf.lastIndexOf('</div>',i)-1;
				var subst=this.tf.substr(0,i),
				divst=subst.match(/<div(>|( style=";))/gi),
				divcl=subst.match(/<\/div>/gi);

				divst=divst ? divst.length : 0;
				divcl=divcl ? divcl.length : 0;

				if(divst==divcl+1){
					var divscompl=$(this.tf.substr(0,(i+7))), divlen=divscompl.length;
					if(this.divs!=divlen){//if new elements have been translated
						divscompl.slice(this.divs,divlen).each(function(i, e){
							(function(){
								if(this.stopped!==true){
									var k=this.divs+i,//generate index
									txteach=$.trim($(e).html()), from;
									this.finalarr[k]=txteach;//create an array for complete callback

									from=(this.from.length<2 && this.detlang) ? this.detlang : this.from;//set det.source lang, if unset

									if(this.fn){//called from function
										if(this.string)
											this.txtorig=[this.txtorig];
										this.opt.each.call(this, k, txteach, this.txtorig[k], from, this.to, this.opt, this.num);
									}else{//called from method
										this.translateMethodEach(k, this.jqt[k], txteach, this.txtorig[k], from, this.to, this.opt, this.num);
										this.opt.each.call(this, k, this.jqt[k], txteach, this.txtorig[k], from, this.to, this.opt, this.num);
										this.split.jqt.push(this.jqt[k]);
										this.split.txtorig.push(this.txtorig[k]);
										this.split.finalarr.push(txteach);
									}
								}
							}).call(that);
						})
						this.divs=divlen;
					}
					break;
				}
			}

			//---------translate one part of text-----------
			if(this.tt.length>0){
				google.language.translate(this.tt, this.from, this.to, function(result){
					(function(){
						if(result.error)
							return this.opt.error.call(this, result.error, this.tt, this.from, this.to, this.opt, this.num);


						this.tf=this.tf+result.translation;
						this.detlang=result.detectedSourceLanguage;
						if( /[\.\?\!;:]$/.exec(this.tf) )
							this.tf=this.tf+' ';

						this.translate();
					}).call(that);
				});
				this.num++;
				this.split.num++;

				if(this.fn)
					return this;
			}else{

				//------------translation complete------------
				if(this.opt.split && (this.n < this.jq.length)){//process remaining elements
					var n=this.n;
					this.jq=$($.grep(this.jq, function(e, i){
						return (i>n);
					}));
					this.jqt=[];
					this.txtorig=[];
					this.n=-1;
					return this.process();
				}

				if(!this.tf)
					return;

				this.tf=this.tf.replace(/\s*$/,'');
				//this.tf=this.tf.replace(/<br>/g,"\n");
				var from=(this.from.length<2 && this.detlang) ? this.detlang : this.from;

				if(this.timeout)
					clearTimeout(this.timeout);

				if(this.fn){//called from function
					if(this.string){
						this.finalarr=this.finalarr[0]; this.txtorig=this.txtorig[0];
					}
					this.opt.complete.call(this, this.finalarr, this.txtorig, from, this.to, this.opt, this.num);
				}else
					this.opt.complete.call(this, this.jqo, $(this.jqt), this.finalarr, this.txtorig, from, this.to, this.opt, this.num);
			}
		},


		translateMethod: function(jq, a, b, c){
			var that=this, opt={}, from, to;
			this.fn=false;
			this.stopped=false;
			this.jq=jq;
			this.jqo=jq;

			if(!$isString(a))
				return this.jqo;
			if(!b && !c){
				from=''; to=a;
			}
			if(!c && b){
				if(typeof b=='object'){
					from=''; to=a; opt=b;
				}else{
					from=a; to=b;
				}
			}
			if(a && b && c){
				from=a; to=b; opt=c;
			}
			this.from=from; this.to=to;

			this.opt=opt=$.extend({
				walk: true,
				returnAll: false,
				replace: true,
				translate:true,
				limit: 500,
				rebind: true,
				data: false,
				setLangAttr: false,
				subject: true,
				not: '',
				comments: false,
				altAndVal:true,
				split: false,
				async: false,
				start: $fn,
				error: $fn,
				each: $fn,
				complete: $fn,
				onTimeout: $fn,
				timeout: 0
			}, $.fn.translate.defaults, opt);

			if(opt.timeout>0){
				this.timeout=setTimeout(function(){
					opt.onTimeout.call(that, jq, from, to, opt);
				}, opt.timeout);
			}

			this.split={};
			if(opt.async===true)
				opt.async=2;
			opt.start.call(this, this.jqo, from, to, opt);

			if(opt.async || opt.split){
				this.processInit();
				return this.jqo;
			}else
				return this.processInit();
		},


		translateMethodEach: function(i, el, tff, orig, from, to, opt, num){
			var that=this, e=$(el), type;
			//--------------set data--------------
			if(opt.data===true){
				if($isString(opt.subject)){
					$.data(el,'translation.'+from+'.'+opt.subject, orig);
					$.data(el,'translation.'+ to +'.'+opt.subject, tff);
				}else{

					if(opt.altAndVal && (el.tagName.toLowerCase()=='img' || el.tagName.toLowerCase()=='input')){
						if(el.tagName.toLowerCase()=='img'){
							$.data(el,'translation.'+from+'.'+'alt', orig);
							$.data(el,'translation.'+ to +'.'+'alt', tff);
						}else{
							type=(e.attr('type') || '').toLowerCase();
							if(type=='text' || type=='button' || type=='submit'){
								$.data(el,'translation.'+from+'.'+'value', orig);
								$.data(el,'translation.'+ to +'.'+'value', tff);
							}
						}
					}else if(el.tagName.toLowerCase()=='textarea'){
						$.data(el,'translation.'+from+'.'+'value', orig);
						$.data(el,'translation.'+ to +'.'+'value', tff);
					}else{
						$.data(el,'translation.'+from+'.'+'html', orig);
						$.data(el,'translation.'+ to +'.'+'html', tff);
					}
				}
			}

			//------------set html attr--------------
			if(opt.setLangAttr===true)
				e.attr('lang',to);
			if($isString(opt.setLangAttr))
				e.attr(opt.setLangAttr,to);

			//---------------replace----------------
			if(opt.replace===true){
				if($isString(opt.subject))
					e.attr(opt.subject, tff);
				else{

					if(from=='ar')
						e.css('direction','ltr');
					if(to=='ar')
						e.css('direction','rtl');
					if(e.css('text-align')==('right' || 'left')){
						if(from=='ar')
							e.css('text-align','right');
						if(to=='ar')
							e.css('text-align','right');
					}

					if(opt.altAndVal && (el.tagName.toLowerCase()=='img' || el.tagName.toLowerCase()=='input')){
						if(el.tagName.toLowerCase()=='img')
							e.attr('alt', tff);
						else{
							type=(e.attr('type') || '').toLowerCase();
							if(type=='text' || type=='button' || type=='submit')
								e.val(tff);
						}
					}else if(el.tagName.toLowerCase()=='textarea')
						e.val(tff);
					else{
						if(opt.rebind===true){//rebind event handlers when html was translated
							var k=e.find('*').not('script').clone(true);
							e.html(tff);
							copyEvents(k, e.find('*'));
						}else
							e.html(tff);
					}
				}
			}
		},


		translateFunction:function(t, a, b, c){
			var that=this, opt={}, from, to;
			this.fn=true;
			this.stopped=false;
			if(!$isSet(t))
				return this;
			if(!b && !c){
				from=''; to=a;
			}
			if(!c && b){
				if(typeof b=='object'){
					from=''; to=a; opt=b;
				}else{
					from=a; to=b;
				}
			}
			if(a && b && c){
				from=a; to=b; opt=c;
			}
			this.from=from; this.to=to;

			this.opt=opt=$.extend({
				limit: 500,
				comments: false,
				start: $fn,
				error: $fn,
				each: $fn,
				complete: $fn,
				onTimeout: $fn,
				timeout: 0
			}, $.translate.defaults, opt, {
				split:false,
				async:false
			});

			if(opt.timeout>0){
				this.timeout=setTimeout(function(){
					opt.onTimeout.call(that, t, from, to, opt);
				}, opt.timeout);
			}
			this.split={};
			opt.start.call(this, t, from, to, opt);

			if($isString(t))
				if(this.opt.comments===false)
					t=this.strip(t);
				else{
					if(this.opt.comments===false)
						for(var i=0; i<t.length; i++)
							t[i]=this.strip(t[i]);
				}

			this.txtorig=t;

			return this.translateInit();
		},



		detectInit: function(){
			this.k=0;
			this.arr_langCode=[];
			this.arr_lang=[];
			this.arr_result=[];
			this.stopped=false;

			return this.detect();
		},

		detect: function(){
			if(this.stopped===true)
				return;
			var that=this;
			google.language.detect(this.t[this.k].substring(0, this.opt.limit*1), function(result){
				(function(){
					if(!result.error){
						var language=this.getLanguage(result.language);
						this.arr_langCode.push(result.language);
						this.arr_lang.push(language);
						this.arr_result.push(result);

						//each:
						if(this.fn===false){
							var e=this.jqt[this.k];
							if(this.opt.setLangAttr===true)
								$(e).attr('lang', result.language);
							if($isString(this.opt.setLangAttr))
								$(e).attr(this.opt.setLangAttr, result.language);
							this.opt.each.call(this, this.k, e, this.t[this.k], result.language, language, result, this.opt);
						}else
							this.opt.each.call(this, this.k, this.t[this.k], result.language, language, result, this.opt);

						//complete:
						if(this.k==this.len-1){
							if(this.string===true)
								return this.opt.complete.call(this, this.t[0], this.arr_langCode[0], this.arr_lang[0],  this.arr_result[0], this.opt);
							else if(this.fn===true)
								return this.opt.complete.call(this, this.t, this.arr_langCode, this.arr_lang,  this.arr_result, this.opt);
							else
								return this.opt.complete.call(this, this.jqt, this.t, this.arr_langCode, this.arr_lang, this.arr_result, this.opt);
						}else{
							this.k++;
							return this.detect();
						}
					//error:
					}else{
						if(this.fn===false)
							return this.opt.error.call(this, result.error, this.jqt[this.k], this.t[this.k], this.k, this.opt);
						else
							return this.opt.error.call(this, result.error, this.t[this.k], this.k, this.opt);
					}
				}).call(that);
			});

			return this;
		},


		detectMethod: function(jq, opt){
			var that=this;
			this.jq=this.jqo=jq;
			this.fn=false;
			this.string=false;
			this.t=[];
			this.arr_e=[];
			this.split={};

			opt=$.extend({
				start: $fn,
				each: $fn,
				complete: $fn,
				error: $fn,
				setLangAttr: true,
				subject: true,
				limit: 500,
				walk: false,
				returnAll: false,
				not: '',
				altAndVal:false
			}, $.fn.language.defaults, opt, {
				//internal:
				async:false,
				split:false
			});

			if(opt.walk===true && opt.returnAll===false)
				opt.returnAllInt=false;
			this.opt=opt=$.extend(opt, {
				translate:false,
				returnAll:true
			});

			opt.start.call(this, jq, opt);

			this.jqt=this.processInit().each(function(i, e){
				var subject;
				e=$(e);
				if(opt.subject===true)
					subject=e.is(':input') ? e.val() : e.text();
				else if($isString(opt.subject))
					subject=e.attr(opt.subject);

				that.t.push(subject);
			})
			this.len=this.jqt.length;

			this.detectInit();

			if(opt.returnAllInt===false)
				return  this.jqo;
			else
				return this.jqt;
		},


		detectFunction: function(t, opt){
			if(!$isSet(t))
				return this;
			this.opt=opt=$.extend({
				start: $fn,
				each: $fn,
				complete: $fn,
				error: $fn,
				limit: 500
			}, $.language.defaults, opt);

			opt.start.call(this, t, opt);

			if($isString(t)){
				t=[t]; this.string=true;
			}

			this.t=t;
			this.len=t.length;
			this.fn=true;

			return this.detectInit();
		},

		strip: function(t){
			return t.replace(/<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)>/g,'');
		},

		stop: function(){
			this.stopped=true; return this;
		},

		getLanguage: function(langCode, format){
			var lang='unknown';
			for(l in google.language.Languages)
				if(google.language.Languages[l]==langCode){
					lang=l; break;
				}
			if(!$isSet(format))
				format='uppercase';
			switch(format){
				case 'lowercase': lang=lang.toLowerCase(); break;
				case 'uppercase': lang=lang; break;
				case 'capitalize': lang=lang.substring(0,1).toUpperCase()+lang.substring(1).toLowerCase(); break;
			}
			return lang;
		},

		getLanguages: function(translatable){
			if(!$isSet(translatable))
				return google.language.Languages;
			var langobj=google.language.Languages;
			translatable={};
			for (var i in langobj)
				if(google.language.isTranslatable(langobj[i]))
					translatable[i]=langobj[i];
			return translatable;
		}
	}


	translate.prototype.init.prototype=translate.prototype;



	$.fn.translate=function(a, b, c){
		return translate().translateMethod(this, a, b, c)
	}
	$.fn.translate.defaults={}

	$.translate=function(t, a, b, c){
		return translate().translateFunction(t, a, b, c)
	}
	$.translate.defaults={}

	$.fn.language=function(opt){
		return translate().detectMethod(this, opt)
	}
	$.fn.language.defaults={}

	$.language=function(t, opt){
		return translate().detectFunction(t, opt)
	}
	$.language.defaults={}

	$.fn.nodesContainingText=function(opt){
		var opt=$.extend({
			not: '',
			async: false,
			altAndVal:false,
			each: $fn,
			complete: $fn
		}, $.fn.nodesContainingText.defaults, opt, {
			//internal:
			nct: true,
			subject: true,
			walk: true,
			returnAll: true,
			translate:false
		})
		return this.translate('en', opt)
	}
	$.fn.nodesContainingText.defaults={}



	var interval, intervalCount=0,
	//you can modify these values for checking the $.translate.ready function:
	intervalCountLimit=60,
	intervalDelay=500;

	function checkReadyFn(){
		if(typeof $.translate.ready=='function'){
			clearInterval(interval);
			return $.translate.ready();
		}
		if(++intervalCount>intervalCountLimit)
			clearInterval(interval);
	}

	$.translate.langLoaded=function(){
		interval=setInterval(checkReadyFn, intervalDelay);
	}

	$.translate.loadLang=function(){
		google.load('language', '1', {
			'callback' : $.translate.langLoaded
			});
	}

	$.translate.initLoader=function(key){
		if(typeof google!='undefined' && typeof google.load!='undefined')
			return $.translate.loadLang();
		$.getScript('https://www.google.com/jsapi?'+(key ? 'key='+key : ''), $.translate.loadLang);
	}

	$.translate.initLoader()

})(jQuery);