(function($) {
    
    function shuffle(a) {
        var i = a.length, j;
        while (i) {
            var j = Math.floor((i--) * Math.random());
            var t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
    }
    
    function randomAlphaNum() {
        var rnd = Math.floor(Math.random() * 62);
        if (rnd >= 52) return String.fromCharCode(rnd - 4);
        else if (rnd >= 26) return String.fromCharCode(rnd + 71);
        else return String.fromCharCode(rnd + 65);
    }
    
    $.fn.rot13 = function() {
        this.each(function() {
            $(this).text($(this).text().replace(/[a-z0-9]/ig, function(chr) {
                var cc = chr.charCodeAt(0);
                if (cc >= 65 && cc <= 90) cc = 65 + ((cc - 52) % 26);
                else if (cc >= 97 && cc <= 122) cc = 97 + ((cc - 84) % 26);
                else if (cc >= 48 && cc <= 57) cc = 48 + ((cc - 43) % 10);
                return String.fromCharCode(cc);
            }));
        });
        return this;
    };
    
    $.fn.scrambledWriter = function() {
        this.each(function() {
            var $ele = $(this), str = $ele.text(), progress = 0, replace = /[^\s]/g,
                random = randomAlphaNum, inc = 3;
            $ele.text('');
            var timer = setInterval(function() {
                $ele.text(str.substring(0, progress) + str.substring(progress, str.length - 1).replace(replace, random));
                progress += inc
                if (progress >= str.length + inc) clearInterval(timer);
            }, 100);
        });
        return this;
    };
    
    $.fn.typewriter = function() {
        this.each(function() {
            var $ele = $(this), str = $ele.text(), progress = 0;
            $ele.text('');
            var timer = setInterval(function() {
                $ele.text(str.substring(0, progress) + (progress & 1 ? '_' : ''));
                progress  = progress  + 1;
                if (progress > str.length) clearInterval(timer);
            }, 100);
        });
        return this;
    };
    
    $.fn.typewriternew = function(theTypeText) {
        this.each(function() {             
            var $ele = $(this), str = $ele.text(), initstr, progress = 0;
            theTypeText = (typeof theTypeText == 'undefined' ? $ele.text() : (theTypeText.length > 0 ? theTypeText : $ele.text()) );
            $ele.text('');
            str     = theTypeText;
            initstr = theTypeText;
            initstr = initstr.replace('_', '');            
            var theLast = initstr.length;
            var firstStart= 0;
            var secondStart= 0;
            var thirdsStart= 0;                         
            var signStart = 0;
            var handStart = 0;
            var handPause = 0;
            var putText   = '';
            var newLitera = '';             
            var timer = setInterval(function() {
                
                putText  = str.substring(0, progress)+(progress%2?'~':'_');
                                                                  
                $ele.text(putText);
                progress  = progress  + 1;                
                if (progress > theLast)  { clearInterval(timer); $ele.text(initstr); };                
            }, 10);
            
            thisTypeW = timer;             
        });
        return this;
    };
        
    
    $.fn.typewriternew_superok2 = function(theTypeText) {
        this.each(function() {             
            var $ele = $(this), str = $ele.text(), initstr, progress = 0;
            theTypeText = (typeof theTypeText == 'undefined' ? $ele.text() : (theTypeText.length > 0 ? theTypeText : $ele.text()) );
            $ele.text('');
            str     = theTypeText;
            initstr = theTypeText;
            initstr = initstr.replace('_', '');            
            var theLast = initstr.length;
            var firstStart= 0;
            var secondStart= 0;
            var thirdsStart= 0;                         
            var signStart = 0;
            var handStart = 0;
            var handPause = 0;
            var putText   = '';
            var newLitera = '';             
            var timer = setInterval(function() {
                thisText  = str.substring(0, progress); 
                newLitera = str.substring(0, (progress + 1));                 
                if (signStart ==  0)
                { putText   = '';
                  signStart = 2;  }
                else if (signStart ==  1)
                { putText   = '';                  
                  signStart = 2; }                                    
                else if (signStart ==  2)
                { putText   = thisText;                               
                  signStart = 3; }                                    
                else if (signStart ==  3)
                { putText   = thisText  + (progress & 1 ? '~' : '');                 
                  signStart = 4;  }
                else if (signStart ==  4)
                { putText   = thisText  + (progress & 1 ? '_' : '');                      
                  signStart = 5; }                                     
                else  if (signStart ==  5)
                { //newLitera = str.substring(0, (progress + 1));
                  //putText   = newLitera;    
                  putText   = newLitera  + (progress & 1 ? '~' : '');                
                  progress  = progress  + 1;
                  handPause = 0;
                  signStart = 4; };
                                  
                $ele.text(putText);                
                if (progress > theLast)  { clearInterval(timer); $ele.text(initstr); };                
            }, 1);
            
            thisTypeW = timer;             
        });
        return this;
    };
        
    $.fn.typewriternew_superok = function(theTypeText) {
        this.each(function() {             
            var $ele = $(this), str = $ele.text(), initstr, progress = 0;
            theTypeText = (typeof theTypeText == 'undefined' ? $ele.text() : (theTypeText.length > 0 ? theTypeText : $ele.text()) );
            $ele.text('');
            str     = theTypeText;
            initstr = theTypeText;
            initstr = initstr.replace('_', '');            
            var theLast = initstr.length;
            var firstStart= 0;
            var secondStart= 0;
            var thirdsStart= 0;                         
            var signStart = 0;
            var handStart = 0;
            var handPause = 0;
            var putText   = '';
                        
            var timer = setInterval(function() {
                thisText  = str.substring(0, progress);                  
                if (signStart ==  0)
                { putText   = '';
                  signStart = 2;  }
                else if (signStart ==  1)
                { putText   = '';                  
                  signStart = 2; }                                    
                else if (signStart ==  2)
                { putText   = thisText;                               
                  signStart = 3; }                                    
                else if (signStart ==  3)
                { putText   = thisText  + (progress & 1 ? '~' : '');                 
                  signStart = 4;  }
                else if (signStart ==  4)
                { 
                  if (handStart ==  0)
                  { putText   = thisText  + (progress & 1 ? '~' : '');  
                    handStart = 2;  }
                  else if (handStart ==  1)
                  { putText   = thisText + (progress & 1 ? '_' : ''); 
                    handStart = 2;  }
                  else if (handStart == 2)
                  { putText   = thisText  + (progress & 1 ? '_' : '');  
                    handStart = 0;  
                    signStart = 5;  };                                   
                  }                                     
                else  if (signStart ==  5)
                      { newLitera = str.substring(0, (progress + 1));
                        putText   = newLitera;
                        progress  = progress  + 1;
                        handPause = 0;
                        signStart = 3; };
                                  
                $ele.text(putText);                
                if (progress > theLast)  { clearInterval(timer); $ele.text(initstr); };                
            }, 1);
            
            thisTypeW = timer;             
        });
        return this;
    };
            
  $.fn.typewriternew_home = function(theTypeText) {
        this.each(function() {             
            var $ele = $(this), str = $ele.text(), initstr, progress = 0;
            theTypeText = (typeof theTypeText == 'undefined' ? $ele.text() : (theTypeText.length > 0 ? theTypeText : $ele.text()) );
            $ele.text('');
            str     = theTypeText;
            initstr = theTypeText;
            initstr = initstr.replace('_', '');            
            var theLast = initstr.length;
            var firstStart= 0;
            var secondStart= 0;
            var thirdsStart= 0;                         
            var signStart = 0;
            var handStart = 0;
            var handPause = 0;
            var putText   = '';
                        
            var timer = setInterval(function() {
                thisText  = str.substring(0, progress);                  
                if (signStart ==  0)
                { putText   = '~';
                  if (firstStart  ==  0)
                  { firstStart  = 1;  }
                  else if (firstStart ==  1)
                  { firstStart  = 2;  }
                  else if (firstStart ==  2)
                  { firstStart  = 0;
                    signStart = 1;  };  }
                else if (signStart ==  1)
                { putText   = '_';
                  if (secondStart ==  0)
                  { secondStart = 1;  }
                  else if (secondStart  ==  1)
                  { secondStart = 2;  }
                  else if (secondStart  ==  2)
                  { secondStart = 0;                  
                    signStart = 2;  };  }                                    
                else if (signStart ==  2)
                { putText   = thisText;
                  if (thirdsStart ==  0)
                  { thirdsStart =  1; }
                  else if (thirdsStart  ==  1)
                  { thirdsStart = 0;                                 
                    signStart = 3;  };  }                                    
                else if (signStart ==  3)
                { putText   = thisText  + (progress & 1 ? '~' : '');                 
                  signStart = 4;  }
                else if (signStart ==  4)
                { 
                  if (handStart ==  0)
                  { putText   = thisText  + (progress & 1 ? '~' : '');  
                    handStart = 1;  }
                  else if (handStart ==  1)
                  { putText   = thisText + (progress & 1 ? '_' : ''); 
                    handStart = 2;  }
                  else if (handStart == 2)
                  { putText   = thisText  + (progress & 1 ? '_' : '');  
                    handStart = 0;  
                    signStart = 5;  };                                   
                  }                                     
                else  if (signStart ==  5)
                      { newLitera = str.substring(0, (progress + 1));
                        putText   = newLitera;
                        if (handPause ==  0)
                        { handPause = 1;  }
                        else if (handPause  ==  1)                                    
                              { progress  = progress  + 1;
                                handPause = 0;
                                signStart = 3; }; };
                                  
                $ele.text(putText);                
                if (progress > theLast)  { clearInterval(timer); $ele.text(initstr); };                
            }, 22);            
        });
        return this;
    };
            
    $.fn.unscramble = function() {
        this.each(function() {
            var $ele = $(this), str = $ele.text(), replace = /[^\s]/,
                state = [], choose = [], reveal = 25, random = randomAlphaNum;
            
            for (var i = 0; i < str.length; i++) {
                if (str[i].match(replace)) {
                    state.push(random());
                    choose.push(i);
                } else {
                    state.push(str[i]);
                }
            }
            
            shuffle(choose);
            $ele.text(state.join(''));
            
            var timer = setInterval(function() {
                var i, r = reveal;
                while (r-- && choose.length) {
                    i = choose.pop();
                    state[i] = str[i];
                }
                for (i = 0; i < choose.length; i++) state[choose[i]] = random();
                $ele.text(state.join(''));
                if (choose.length == 0) clearInterval(timer);
            }, 100);
        });
        return this;
    };
    
})(jQuery);
