
(function ($){
	
  
  $.fn.decimalMask = function (mask){
    if (!mask || !mask.match){
      throw 'Provide some mask to decimalMask plugin please.';
    }
    
    var
      v,
      is = (function(){v = mask.match(/[0-9]{1,}/);return v!== null ? v[0].length : 0})(),
      ds = (function(){v = mask.match(/[0-9]{1,}$/);return v !== null ? v[0].length : 0})(),
      sep = (function(){v = mask.match(/,|\./);return v !== null ? v[0] : null})(),
	  matcher = null,
      placeholder='_',
	  len = (is + ds + (sep === null ? 0 : 1)),
	  free=false;
	  debug='',
	  tester = null;
		
    if (sep === null){
      tester = new RegExp('^[0-9]{0,'+is+'}$');
      matcher = new RegExp('[0-9]{0,'+is+'}','g');
      
    }else{
      tester = new RegExp('^[0-9]{0,'+is+'}'+(sep === '.' ? '\\.' : ',')+'[0-9]{0,'+ds+'}$|^[0-9]{0,'+is+'}'+(sep === '.' ? '\\.' : ',')+'$|^[0-9]{0,'+is+'}$');
      matcher = new RegExp('[0-9]{0,'+is+'}'+(sep === '.' ? '\\.' : ',')+'[0-9]{0,'+ds+'}|[0-9]{0,'+is+'}'+(sep === '.' ? '\\.' : ',')+'|[0-9]{0,'+is+'}','g');
    }
    
    if(mask.substr(0,1) == '*'){
            len=mask.substr(1)*2;
            is=len/2;
            ds=is;
            free=true;
    }
    
    /*if(typeof($(this).val()) == 'undefined'){
        $(this).attr('value', '');
        alert($(this).val());
    }*/
    try{
        if(!sep && !free){
                var p = $(this).val().indexOf('.');
                if(p>=0){
                    $(this).val($(this).val().substr(0,p));
                }
        }
        if (!free) $(this).val($(this).val().replace('.',sep))

        $(this)
          .attr('maxlength', len+1)
          .bind('keydown',{ov:$(this).val()},handlerDown)
          .bind('keypress',{ov:$(this).val()},handlerPress)
          .bind('keyup',{ov:$(this).val()},handler)
          .bind('blur',{ov:$(this).val()},handlerBlur)
          .bind('focus',{ov:$(this).val()},handlerFocus);
    }
    catch(e){}

	function unMask(input){
		var i;
		var chars;
		chars = input.val().split('');
		for(i=0;i<chars.length;i++){
			if(chars[i] == placeholder)
				chars[i]= ' ';
		}
		//alert (jQuery.trim(chars.join('')));
		return jQuery.trim(chars.join(''));
		
	}
	
	function writeMask(input,start,back){
		
		var sepFound=false;
		var sepPos=0;
		var i;
		var chars;
		var caretPos=-1;
		
		//if(start>=0) alert('writemask');
		chars = input.val().substr(0,len).split('');
		var unm = unMask(input);
		if(unm==sep || unm == ''){
			for(i=0;i<is;i++)
				chars[i]=' ';
			if(sep!=null)
				chars[i]=sep;
				i++;
			if(sep){
				for(;i<ds;i++)
					chars[i]=' ';
				start=0;	
			}	
		}
		
		for(i=chars.length;i<len;i++)
			chars[i]=' ';
		for(i=0;i<is;i++){
			
			if(sep && chars[i]==sep){
				sepFound=true;
				sepPos=i;
				i++;
				break;
			}
			if(chars[i]==' ' || chars[i]==placeholder){
				chars[i]=placeholder;
				if(caretPos == -1) 
					caretPos=i;
			}	
		}
		//i++;
		if(sep!=null && !sepFound){
			chars[i]=sep;
			sepPos=i;
			i++;
		}
		if(sep){
                    for(var j=i;j<i+ds;j++){
                        if(chars[j]==' ' || chars[j]==placeholder){
                            chars[j]=placeholder;
                            if(caretPos == -1){
                                caretPos=j;
                            }
                        }
                    }
		}	
		
		if(sep)
			chars.length = sepPos+1+ds;
		else
			chars.length = is;
		debug='';
		debug+='start = ' + start +'\n';
		debug+='is = ' + is +'\n';
		debug+='ds = ' + ds +'\n';
		debug+='len = ' + len +'\n';
		if(start>=0 && i==(is+1)){
			if(sep && chars[start]==sep)
				start+= (back ? 0 : 1);
		}	
		else if(sep && chars[caretPos]==sep){
			caretPos++;
		}	
		debug+='start = ' + start +'\n';
			
		input.val(chars.join(''));
		
		/*var add = is - sepPos;
		for(var k=0;k<add;k++)
			input.val(placeholder + input.val());
		*/
		if(start>=0)
			input.caret(start,start);
		else if(caretPos>=0)
			input.caret(caretPos,caretPos);
	}
	
	function handlerDown(e){

		var self = $(e.currentTarget);

		//var keycode = getKeyCode(e);
		var keycode = (e.which) ? e.which : e.keyCode
		//alert(keycode);
		if(keycode == 190 || keycode == 110)
		{
			if(!sep && !free)
				return false;
			if(sep)
			{
				var start = self.caret().start;
				var pos = self.val().indexOf(sep);
				if(start>= pos)
					return false;
			}
		}
		//alert('keycode down ' + keycode);
		return true;
	}

        function handlerPress(e){
		
		var self = $(e.currentTarget);
		
		var keycode = getKeyCode(e);
		//alert(keycode);
		if(keycode == 46 || keycode == 8 || keycode == 37 || keycode == 39)
			return true;
		if( (sep && self.caret().start >= len) || (!sep && self.caret().start >= len/2) ){
			if(keycode!=9)
                            return false;
                }
		if(free)
			return true;
		if(keycode > 31 && (keycode < 48 || keycode > 57) )
			return false;
			
		return true;	
	}
	
    function handlerFocus(e){
          var self = $(e.currentTarget);
	  writeMask(self,-1,false);
	}
    
    function handlerBlur(e){
		var self = $(e.currentTarget);

		var chars = unMask(self).split('');
		if(sep && chars[chars.length-1] == sep)
			chars.length = chars.length -1;
		self.val(chars.join(''));
		
		//self.val(unMask(self));
	  
	}
    
	function getKeyCode(e){
		var keycode;
		
		if(e.keyCode) // IE
			keycode = e.keyCode;
		else if(e.Which)
			keycode = e.Which; // FireFox
		else
			keycode = e.charCode; // Il resto
		
		return keycode;
	}
	
	
	function handler(e){
		var self = $(e.currentTarget);
      //alert(self.val());
		
		var keycode = getKeyCode(e);
		if( (keycode==39 && e.shiftKey==1) || (keycode==37 && e.shiftKey==1)  || (keycode==16 && e.shiftKey==0) ){
                    //alert('shift');
                    return;
                }
	  	  //alert(self.val() + ' -- ' + keycode);
	  	  //alert(self.val() + ' -- ' + String.fromCharCode(keycode));
		
		var start = self.caret().start;
		var end = self.caret().end;
		var text = unMask(self);
		var back=false;
		if(keycode==8 || keycode==37)
		{
			back=true;
		}
		if (!free && text !== e.data.ov){
      
			if (!tester.test(text)){
				var r = text.match(matcher);
				//alert(r[0]);
				self.val(r === null ? '' : r[0]);
				text = self.val();
			}
			e.data.ov = text;
		}
		//alert(self.val());
                writeMask(self,start,back);
		//alert(keycode + ' -- '  + e.shiftKey);
		//alert(debug);

    }
  }
})(jQuery);
