function LipikaarLanguageMapManager(language)
{
	this.languages = [];
}

LipikaarLanguageMapManager.prototype = {
	getMapping : function(script)
	{
		if (this.languages[script]==undefined)
		{
			var url = "/" + basePath + "/languages/" + script + "_map" + ".24082010.js";
			var httpRequest;
				try {
						httpRequest = new ActiveXObject('Msxml2.XMLHTTP');
					}
					catch (e1) {
						try {
							httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
						}
						catch (e2) {
							try {
								httpRequest = new XMLHttpRequest();
							}
							catch (e3) {
								httpRequest = false;
							}
						}
					}
					httpRequest.open('GET', url, false);
					httpRequest.send(null);
					eval("this.languages['" + script + "']=" + httpRequest.responseText);
		}
		return (this.languages[script]);
	}
};
var LM = new LipikaarLanguageMapManager();

function Lipikaar() {
	this.languageObj = new LanguageObject();
	this.targetName = '';
	this.language = '';
	this.contextHandler = new ContextHelpHandler(this.languageObj);
	this.autoSaveOn = false;
	this.languageName = '';
}

Lipikaar.prototype = {

	$ : function(name) {
		return document.getElementById(name);
	},

	init : function() {

		this.languageObj.targetDOMElement = this.$(this.targetName);
		YAHOO.util.Event.addListener(this.languageObj.targetDOMElement,
				"keypress", this.handleEvent, this, true);
		
		YAHOO.util.Event.addListener(this.languageObj.targetDOMElement,
				"blur", function() {
				this.contextHandler.hideContextHelp();
				if(this.autoSaveOn) {
					this.languageObj.autoSaveTypedText(this.languageName);}
				}, this, true);

		YAHOO.util.Event.addListener(this.languageObj.targetDOMElement,
				"focus", this.clearTarget, this, true);
												
		var ieSpecialKeyWorkAround = new YAHOO.util.KeyListener(
				this.languageObj.targetDOMElement, this.languageObj
						.getSpecialKeys(),
				this.languageObj.ignoreIeSpecialEvent, this, true);
		ieSpecialKeyWorkAround.enable();

		this.languageObj.currentLanguage = this.language;
		this.loadLanguage(this.languageObj.currentLanguage);

		/*create help element*/
		var contextHelp = window.document.createElement("span");
		contextHelp.id="lipikaarToolTip";
		window.document.body.appendChild(contextHelp);

	},

	loadLanguage : function(languageKey) {
		this.languageObj.initMapping(languageKey);
	},

	handleEvent : function(e) {
		var lipiCode = e.charCode || e.keyCode;
		// standard ascii value across browsers
		
		if (this.languageObj.isEventToBeIgnored(e)) {
			this.languageObj.clearStack();
			this.contextHandler.hideContextHelp();
			return true; // These do not interest us.
		}

		this.languageObj.addToStack(lipiCode);

		// First check if a mapping exists.
		if (!this.languageObj.mappingOf(String.fromCharCode(lipiCode))) {

			this.languageObj.clearStack();
			this.contextHandler.hideContextHelp();
			// Prevent Default Action.
			if (!document.selection) { // IE workaround
				e.preventDefault();
			}
			return false;
		}
		var scrollTop = this.languageObj.targetDOMElement.scrollTop; // FF AutoScrolling Fix

		this.languageObj.processKeyEvent(lipiCode);

		this.languageObj.targetDOMElement.scrollTop = scrollTop;
		// Prevent Default Action.
		if (!document.selection) { // IE workaround
			e.preventDefault();
		}
		this.contextHandler.updateContextHelp(this.languageObj.targetDOMElement);
		return false;
	},

	clearTarget : function(e) {
		if (this.languageObj.targetDOMElement.defaultValue == this.languageObj.targetDOMElement.value) {
			this.languageObj.targetDOMElement.value = '';
		}
	}
	
}

function LanguageObject() {
	this.keyStack = new Array();
	this.targetDOMElement = {};
	this.currentLanguage = "";	
	this.mapping = {};
}

LanguageObject.prototype = {

	initMapping : function(languageKey) {

		this.currentLanguage = languageKey;
		this.mapping = LM.getMapping(languageKey);
		this.clearStack(); // Always clear keyStack when changing language maps
	},

	addToStack : function(value) {
		this.keyStack[this.keyStack.length] = value;
	},

	clearStack : function() {
		this.keyStack = new Array();
	},

	processKeyEvent : function(lipiCode) {
		if (this.keyStack.length == 1) { // New element added
			this.insertChar(this.mappingOf(String.fromCharCode(lipiCode)));
		} else { // element added again

			// First test if the string is mapped
			if (this.mappingOf(this.readKeyStackAsString())) {
				this.removeChar();
				this.insertChar(this.mappingOf(this.readKeyStackAsString()));
			} else { // Second, since the string is not mapped, just map the
				// single keypress and insert.
				this.clearStack();
				this.insertChar(this.mappingOf(String.fromCharCode(lipiCode)));
				this.addToStack(lipiCode);
			}
		}
	},

	isEventToBeIgnored : function(ev) {
		var lipiCode = ev.charCode ? ev.charCode : ev.keyCode;

		if (ev.altKey || ev.ctrlKey || lipiCode == 13 || lipiCode == 32) {
			return true;
		}

		if (!document.selection) { // handle the special keys in FF
			if (ev.charCode == 0) {
				return true;
			}
		}
		return false;
	},

	readKeyStackAsString : function(length) {
		var retStr = "";
		var limit = length || this.keyStack.length;
		for (var i = 0;i < limit; i++) {
			retStr += String.fromCharCode(this.keyStack[i]);
		}
		return retStr;
	},

	getPossibleSequences : function(character) {
		var retArr = Array();
		var i = 0;
		var str = character || "";
		while (this.mappingOf(str)) {
			retArr[i] = this.mappingOf(str);
			i++;
			str += character;
		}
		return retArr;
	},

	mappingOf : function(strToMap) {
		return this.mapping[strToMap] || false;
	},
	/**
	 * Function returns the curently mapped character
	 */
	getCurrMappedCharacter : function() {
		var curStr = this.readKeyStackAsString();
		return this.mappingOf(curStr);
	},

	insertChar : function(myValue) {
		var myField = this.targetDOMElement;

		if (document.selection) {// IE support
			myField.focus();
			sel = document.selection.createRange();
			sel.text = myValue;
			sel.moveStart('character', myValue.length);
		} else { // MOZILLA/NETSCAPE support
			if (myField.selectionStart || myField.selectionStart == '0') {
				var startPos = myField.selectionStart;
				var endPos = myField.selectionEnd;
				myField.value = myField.value.substring(0, startPos) + myValue
						+ myField.value.substring(endPos, myField.value.length);
				myField.selectionStart = startPos + myValue.length;
				myField.selectionEnd = myField.selectionStart;
			}
		}
	},

	removeChar : function() {
		myValue = this.mappingOf(this.readKeyStackAsString(this
				.readKeyStackAsString().length
				- 1));
		myField = this.targetDOMElement;

		if (document.selection) {// IE support
			myField.focus();
			sel = document.selection.createRange();
			if (sel.text.length > 0) {
				sel.text = '';
			} else {
				sel.moveStart('character', -myValue.length);
				sel.text = '';
			}
			sel.select();
		} else if (myField.selectionStart || myField.selectionStart == '0') {// MOZILLA/NETSCAPE
			// support
			var startPos = myField.selectionStart;
			var endPos = myField.selectionEnd;
			myField.value = myField.value.substring(0, startPos
					- myValue.length)
					+ myField.value.substring(endPos, myField.value.length);

			myField.selectionStart = startPos - myValue.length;
			myField.selectionEnd = startPos - myValue.length;
		}
	},

	getSpecialKeys : function() {
		return {
			keys : [18, 8, 20, 17, 46, 40, 35, 13, 27, 36, 37, 224, 144, 34,
					33, 19, 44, 39, 145, 16, 32, 9, 38]
		};
	},

	ignoreIeSpecialEvent : function(type, args, me) {
		this.clearStack();
		return true; // These do not interest us.
	},
	
	autoSaveTypedText : function(lang) {
		if (this.targetDOMElement.value == this.targetDOMElement.defaultValue || 
			this.targetDOMElement.value == '') {
			return;
		}
		var me = this;
		var data = 'language=' + lang + 
				   '&vuid=' + document.getElementById("vuid").value + 
				  '&trial_text=' + this.targetDOMElement.value;
		var handler = {
			success : function(o) {
			},
			failure : function(o) {
			},
			scope : me,
			timeout : 7000
		};
		try {
			YAHOO.util.Connect.asyncRequest('POST', "http://www.lipikaar.com/lipikaar_live/auto_save", handler, data);
		} catch (e) {
		}
	}
	
}

/*Context Help Handler */
function ContextHelpHandler(languageObj)
{
	this.languageObj = languageObj;
}
ContextHelpHandler.prototype ={
	getX: function(obj)
	{
		return( obj.offsetParent==null ? obj.offsetLeft : obj.offsetLeft+  this.getX(obj.offsetParent) );
	},
	getY:function (obj)
	{
		return( obj.offsetParent==null ? obj.offsetTop : obj.offsetTop+  this.getY(obj.offsetParent) );
	}
	,
	getWindowSize:function() 
	{
	  var myWidth = 0, myHeight = 0;
	  if( typeof( window.innerWidth ) == 'number' ) {
		//Non-IE
		myWidth = window.innerWidth;
		myHeight = window.innerHeight;
	  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//for IE 6+
		myWidth = document.documentElement.clientWidth;
		myHeight = document.documentElement.clientHeight;
	  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		//IE 4 compatible
		myWidth = document.body.clientWidth;
		myHeight = document.body.clientHeight;
	  }
	  
	  return {'width':myWidth,'height':myHeight};
    }
    ,
	getSelection :function ( el )
	{
		if ( el.selectionStart == undefined )
		{
		var r = document.selection.createRange();

		return new Array( r.start, r.end );
		}
		else
		{
		return new Array( el.selectionStart, el.selectionEnd );
		}
	},
	getCursorCoordinates:function(elem)
	{
		var objTmp=this.getRange(elem);
		if(!objTmp)
		{
			var objTmp =elem;
			//return null
		}
		var c=this.getLeftOffset(objTmp),e=this.getPScroll(objTmp);
		return{x:c.x+e.x,y:c.y+ 17 +e.y}
	},
	getRange :function(elem)
	{	
		return window.document.selection.createRange();
		
	},
	getLeftOffset:function(a)
	{	
		var objTmp=a.offsetLeft,c=a.offsetTop;
		if(a.offsetParent!=null)
		{
			var e=this.getLeftOffset(a.offsetParent);objTmp+=e.x;c+=e.y
		}
		return{x:objTmp,y:c}
	},
	getPScroll:function(a)
	{
		e = (document.documentElement && document.documentElement.scrollLeft) ?
			 document.documentElement.scrollLeft : document.body.scrollLeft;
		f = (document.documentElement && document.documentElement.scrollTop) ?
			 document.documentElement.scrollTop : document.body.scrollTop;
		return new this.objXy(e,f);
	},
	objXy:function(a,objTmp)
	{
		this.x= typeof a!="undefined"?Number(a):undefined;
		this.y= typeof objTmp!="undefined"?Number(objTmp):undefined;
		
	},
	setCursorCoordinatesFf :function(elm)
    {
		var elm,range=elm.selectionStart;
		if(document.getElementById('lipikaar_temp_'+elm.id)==null)
		{
			tempDiv = document.createElement("div")
			tempDiv.id='lipikaar_temp_'+elm.id;	
			tempDiv.style.lineHeight=elm.style.lineHeight;
			tempDiv.style.fontFamily= "monospace";
			tempDiv.style.whiteSpace= "pre-wrap";
			tempDiv.style.position= "absolute";
			document.body.appendChild(tempDiv);
		}
		else
		{
			tempDiv =document.getElementById('lipikaar_temp_'+elm.id);
		}
		tip = document.getElementById('lipikaarToolTip');

 		var cord=this.getLeftOffset(elm);
		tempDiv.style.top = cord.y +  elm.offsetHeight + "px";
		tempDiv.style.left = cord.x  + "px";
		tempDiv.style.width = elm.offsetWidth + "px";
		tempDiv.style.height = elm.offsetHeight + "px";
		this.doMask(elm.value.substring(0,range),cord.x,cord.y,elm,tempDiv,tip);
		tip.style.display="block";
		document.body.removeChild(tempDiv);
		return;
  },
  doMask:function(val,x,y,elm,tempDiv,tip)
  {
	tempDiv.innerHTML = "";
	arrVal = val.split("\n");
	if(arrVal.length>1)
	{
		for(key in arrVal)
		{
			span = document.createElement("span");
 			span.innerHTML = arrVal[key]+"<br>";;
			tempDiv.appendChild(span)
		}		
	}
	else
	{	
		span = document.createElement("span");
		span.innerHTML = val ;
		tempDiv.appendChild(span)	
	}	
	var spanCord=this.getLeftOffset(span);	
	if(tempDiv.offsetHeight >elm.scrollHeight || (elm.type=="text"&&elm.offsetWidth >span.offsetWidth))
	{	
		tip.style.top = ((spanCord.y - tempDiv.offsetHeight) +20 ) +  "px";
	}
	if((tempDiv.offsetWidth >elm.scrollWidth) || (elm.type=="text"&&elm.offsetWidth >span.offsetWidth) )
	{
		tip.style.left = (spanCord.x + span.offsetWidth + 5) + "px";
	}
 	tempDiv.innerHTML = "";	 
  },
  createElem:function(elemName,parentElm,attrib,value,style)
  {
	 
	try
	{
		var dynElm = document.createElement(elemName);
	
		for (key in attrib)
		{
			dynElm.setAttribute(key,attrib[key]);
		}
		for (key in value)
		{
			eval("dynElm."+key+"='"+value[key]+"';");
		}
		for (key in style)
		{
			eval("dynElm.style."+key+"='"+style[key]+"';");
		}

		parentElm.appendChild(dynElm);	
	}
	catch (e)
	{
		alert(e);
	}
	return dynElm
  },	
  showContextHelp: function (x, y) 
	{
		document.getElementById('lipikaarToolTip').style.display='block';
		document.getElementById('lipikaarToolTip').style.left =x + "px";
		document.getElementById('lipikaarToolTip').style.top = y + "px";
		
    },
	hideContextHelp: function () 
	{
		if(document.getElementById('lipikaarToolTip'))
		{
			document.getElementById('lipikaarToolTip').style.display='none';
		}		 
    },
    updateContextHelp: function(textEl)
	{
		var oPositionLeft =  0;
		var oPositionTop =   0;
		
		var mappings = this.languageObj.getPossibleSequences(this.languageObj.readKeyStackAsString(1));
		var contextHelpWin = document.getElementById('lipikaarToolTip');
		if(!contextHelpWin)
		{
			return false;
		}

		contextHelpWin.innerHTML = "";
		
		for (var i = 0;i < mappings.length; i++) 
		{
 			contextHelpWin.style.border="1px solid #CCCCCC";
			contextHelpWin.style.fontSize = "18px";
			contextHelpWin.style.padding = "2px";
			contextHelpWin.style.position = "absolute";			 
			contextHelpWin.style.textAlign = "left";
			contextHelpWin.style.backgroundColor = "#FFFFFF";
			contextHelpWin.style.color = "black";
			var fcolor ="black";
			if (this.languageObj.getCurrMappedCharacter() == mappings[i]) 
			{
				fcolor = "#E86E01";
			}
		   
			contextHelpWin.innerHTML  = contextHelpWin.innerHTML + "<span style='color:"+fcolor+"' >"+mappings[i]+"&nbsp;</span>";
			
		}
		var tipText = "<table cellspacing='0' cellpadding='0' style='font-size:8pt;font-family:verdana;'><tr><td >Type <u><b>"+ this.languageObj.readKeyStackAsString(1)+ "</u></b> again for next character.</td><td rowspan='2'><img src= 'http://www.lipikaar.com/sites/www.lipikaar.com/files/webmodule/img/lipikaar-context-help-logo.jpg' border='0' valign='top' ></td></tr><tr><td><b><u>x</u></b> - half character <b><u>z</u></b> - special symbols</td></tr></table>";
		contextHelpWin.innerHTML += tipText;
		if(textEl.type=='textarea')
		{
			if(window.getSelection)
			{
				this.setCursorCoordinatesFf(textEl);
			}
			else
			{
				oPositionLeft =  this.getCursorCoordinates(this).x +2 ;
				oPositionTop = 	 this.getCursorCoordinates(this).y ||(this.getY(textEl) + textEl.scrollHeight) +6 ; 
				this.showContextHelp(oPositionLeft,oPositionTop);
			}
		}
		else
		{	 
			
			if(window.getSelection)
			{
				this.setCursorCoordinatesFf(textEl);
			}
			else
			{ 
			  oPositionLeft =  this.getCursorCoordinates(this).x + 12 + this.getX(textEl);
			  if((textEl.offsetWidth + this.getX(textEl)) < oPositionLeft )
			  {
				oPositionLeft = (textEl.offsetWidth + this.getX(textEl));
			  }			  
			  oPositionTop =   this.getY(textEl) + 22;
			  this.showContextHelp(oPositionLeft,oPositionTop);	
			}
		}
     }
 }


