


var TextMaster = (function (){
     
    var dictionary = null;
    
    var config = {
        "warn-function": function(wstr){ dump("Warning" + wstr + "\n"); }
    };
    
     var customSubs = function customSubs(text, strFrom, strTo, strCase, chrFrom, chrTo,chrCase){
        text = text || "";
        !!(strFrom == undefined) && ((TextMasterUI !== undefined) ? strFrom = TextMasterUI.config.stringFromBox.value || "" : strFrom = "");
        !!(strTo == undefined)   && ((TextMasterUI !== undefined) ? strTo = TextMasterUI.config.stringToBox.value || "" : strTo = "");
        !!(strCase == undefined) && ((TextMasterUI !== undefined) ? strCase = TextMasterUI.config.stringCheck.checked || "" : strCase = "");
        !!(chrFrom == undefined) && ((TextMasterUI !== undefined) ? chrFrom = TextMasterUI.config.charFromBox.value || "" : chrFrom = "");
        !!(chrTo == undefined)   && ((TextMasterUI !== undefined) ? chrTo = TextMasterUI.config.charToBox.value || "" : chrTo = "");
        !!(chrCase == undefined) && ((TextMasterUI !== undefined) ? chrCase = TextMasterUI.config.charCheck.checked || "" : chrCase = "");
        
        if((text) && ((strFrom) || (chrFrom))){
            var a, b, c, q, flags;
            a = strFrom.value ? strFrom.value : strFrom;
            a = escapeChars(a);
            b = strTo.value ? strTo.value : strTo;
            flags = "g";
            if((!strCase) || (!strCase.checked)){ flags += "i"; };
            q = new RegExp(a, flags);
            text = text.replace(q,b);
          
            a = chrFrom.value ? chrFrom.value : chrFrom;
            b = chrTo.value ? chrTo.value : chrTo;
            flags = "g";
            if((!chrCase) || (!chrCase.checked)){ flags += "i"; };
            for(var i = 0, ii = a.length;i < ii;i++){
                var s = escapeChars(a.substr(i,1));
                c = new RegExp(s, flags);
                if(b.substr(i,1)){
                    text = text.replace(c, b.substr(i,1));
                } else {
                    text = text.replace(c, "");
                };
            };
            
            return text;
        };
        
        return text;
    };
    
    var stripText = function stripText(text){
        text = text || "";
        
        var charDictionary = {
          '\u20AC' : '\u20AC', '\u00AE' : '(r)', '\u201A' : ',', '\u0192' : 'f', '\u201E' : ',,',
          '\u2026' : '...', '\u0160' : 'S', '\u0152' : 'OE', '\u017D' : 'Z', '\u2018' : "'", '\u2019' : "'", '\u201C' : '"',
          '\u201D' : '"', '\u2022' : '*', '\u2013' : '-', '\u2014' : '-', '\u02DC' : '~', '\u2122' : '(tm)', '\u0161' : 's',
          '\u203A' : '>', '\u0153' : 'oe', '\u017E' : 'z', '\u0178' : 'Y', '\u00A1' : '!', '\u00A2' : ' Cents ',
          '\u00A3' : '\u00A3', '\u00A4' : ' currency ', '\u00A5' : ' Yen ', '\u00A6' : '| ', '\u00A7' : ' section ',
          '\u00A9' : '(c)', '\u00AA' : ' femine ordinal', '\u00AB' : '<<', '\u00AC' : ' (not) ',
          '\u00B0' : ' degrees ', '\u00B1' : ' +/- ', '\u00B2' : '^2', '\u00B3' : '^3', '\u00B4' : '`', '\u00B5' : 'micro',
          '\u00BA' : ' masculine ordinal', '\u00BB' : '>>', '\u00BC' : '1/4', '\u00BD' : '1/2', '\u00BE' : '3/4',
          '\u00BF' : '?', '\u00C6' :'AE', '\u00C7' :'C', '\u00D0' : 'ETH', '\u00D1' : 'N', '\u00D7' : 'x', '\u00D8' : 'O',
          '\u00DD' : 'Y', '\u00DE' : 'TH', '\u00DF' : 'ss', '\u00E6' : 'ae', '\u00E7' : 'c', '\u00F0' : 'eth', '\u00F1' : 'n',
          '\u00F7' : "/", '\u00F8' : 'o', '\u00FD' : 'y', '\u00FE' : 'th', '\u00FF' : 'y'
        };
        
        text = text.replace(/[^\w\s\!\@\#\$\%\^\&\*\(\)\-\+\=\\\/\;\:\"\'\.\[\{\<\}\]\>\?\,_\u007E]/gi, function (ch){
            var replacer = "", c;
            c = ch.charCodeAt(0);
            if((c >= 192) && (c <= 252)){
              if((c >= 192 ) && (c <= 197)){ replacer = 'A'};
              if((c >= 200 ) && (c <= 203)){ replacer = 'E'};
              if((c >= 204 ) && (c <= 207)){ replacer = 'I'};
              if((c >= 210 ) && (c <= 214)){ replacer = 'O'};
              if((c >= 217 ) && (c <= 220)){ replacer = 'U'};
              if((c >= 224 ) && (c <= 229)){ replacer = 'a'};
              if((c >= 232 ) && (c <= 235)){ replacer = 'e'};
              if((c >= 236 ) && (c <= 239)){ replacer = 'i'};
              if((c >= 242 ) && (c <= 246)){ replacer = 'o'};
              if((c >= 249 ) && (c <= 252)){ replacer = 'u'};
            };
            replacer = replacer || (charDictionary[ch] || "");
            
            return replacer;
            
            });
        
        text = normalizeWS(text);
        
        return "" + text;
    };
  
    
    var moreifyText = function moreifyText(text, maxLength, warnFunc){
        text = text || "";
        if(!text){ return ""; };
        
        warnFunc = warnFunc || function(wstr){ dump("Warning: " + wstr + "\n") };
        !!(maxLength == undefined) && ((TextMasterUI !== undefined) ? maxLength = TextMasterUI.config.charMax || 160 : maxLength = 160);
        
        if(type(maxLength) === "function"){
            maxLength = maxLength();
        } else {
            
        };
        
        var a = {}, b = "", warning = "", count = 1;
        a[0] = "";
        
        if(text.length > maxLength ){
          do {
            gregex = new RegExp("^.{" +  (maxLength-10) + "," + (maxLength-6) + "}\\s", "g");
            a = text.match(gregex);
            if(a){
              text = text.substring(a[0].length, text.length);
              a[0] += "-more?" + "\n\n\n";
              b += a[0];
            } else {
              if(text.length > maxLength ){
                warning += (!warning) ? count + " " : "," + count + " "  ;
                a = text.substring(0, (maxLength - 6));
                text = text.substring((maxLength - 6), text.length);
                a += "-more?" + "\n\n\n";
                b += a;
              } else {
                a = text;
                text = "";
                b += a;
              };
            };
            count++;
          } while(text.length > 0);
        } else{ b = text};
        
        (warning) && warnFunc("A word was split at the end of block(s) " +
                                             warning + " please adjust manually");
        return "" + b;
    };
    var minifyText = function minifyText(text){
        grammar = textmasterDictionaries.minify;
        
        text = text || "";
        
        var tokens = [], token, newTokens = [];
        
        tokens = tokenize(text);
        
        for(i=(tokens.length-1);i>=0;i--){
            token = tokens[i].token;
           if(token === "i"){
                tokens[i].token = "I";
                token = "I";
                tokens[i].caseMask = "ucf";
            };
            
            [x, y, z] = grammarLookup(grammar, token, tokens, i, i);
            

            newTokens.unshift(copyToken(tokens[i], x));
            newTokens[0].post = tokens[y].post;
            newTokens.splice(1,(y-z));
            
            if(y-z){
                for(qz=z,qy=y;qz<=qy;qz++){
                    tokens.splice(qz,1,{pre:"",token:"",post:""});
                };
            };
        };
        
       text = "";
        for(i=0,ii=newTokens.length;i<ii;i++){
            text += newTokens[i].token + newTokens[i].post;
        };
        return "" + text;
    };
    

    var ukifyText = function ukifyText(text){
        grammar = textmasterDictionaries.UKify;
        
        text = text || "";
        
        var tokens = [], token, newTokens = [];
        tokens = tokenize(text);
        
        for(i=(tokens.length-1);i>=0;i--){
            token = tokens[i].token;
            if(token === "i"){
                tokens[i].token = "I";
                token = "I";
                tokens[i].caseMask = "ucf";
            };
            
            [x, y, z] = grammarLookup(grammar, token, tokens, i, i);
            
            newTokens.unshift(copyToken(tokens[i], x));
            newTokens[0].post = tokens[y].post;
            newTokens.splice(1,(y-z));
            
            if(y-z){
                for(qz=z,qy=y;qz<=qy;qz++){
                    tokens.splice(qz,1,{pre:"",token:"",post:""});
                };
            };
        };
        
        text = "";
        for(i=0,ii=newTokens.length;i<ii;i++){
            text += newTokens[i].token + newTokens[i].post;
        };

        return "" + text;
    };


    var grammarLookup = function grammarLookup(dict, value, tArray, place, origin, failVal){

        origin = (origin == undefined) ? undefined: origin;

        failVal = (failVal == undefined) ? value: failVal;

        var valueUC, valueUCF, valueLC, valueLCF;
        valueUC = applyCaseMask(value, "uc");
        valueUCF = applyCaseMask(value, "ucf");
        valueLC = applyCaseMask(value, "lc");
        valueLCF = applyCaseMask(value, "lcf")

        if((dict.hasOwnProperty("#default#")) &&  (type(dict["#default#"]) === "string")){
            failVal = dict["#default#"];
        }else{
            if(dict.hasOwnProperty(value)){
                if((dict[value].hasOwnProperty("#default#")) &&  (type(dict[value]["#default#"]) === "string")){
                    failVal = dict[value]["#default#"];
                }
            }else if(dict.hasOwnProperty()){
                if((dict[valueUCF].hasOwnProperty("#default#")) &&  (type(dict[valueUCF]["#default#"]) === "string")){
                    failVal = dict[valueUCF]["#default#"];
                };
            }else if(dict.hasOwnProperty(valueUC)){
                if((dict[valueUC].hasOwnProperty("#default#")) &&  (type(dict[valueUC]["#default#"]) === "string")){
                    failVal = dict[valueUC]["#default#"];
                };
            }else if(dict.hasOwnProperty(valueLCF)){
                if((dict[valueLCF].hasOwnProperty("#default#")) &&  (type(dict[valueLCF]["#default#"]) === "string")){
                    failVal = dict[valueLCF]["#default#"];
                };
            }else if(dict.hasOwnProperty(valueLC)){
                if((dict[valueUC].hasOwnProperty("#default#")) &&  (type(dict[valueLC]["#default#"]) === "string")){
                    failVal = dict[valueLC]["#default#"];
                };
            };
        };
        
        if(type(dict[value]) === "string"){
            return [dict[value], place, origin];
        }else if(type(dict[valueUCF]) === "string"){
            return [dict[valueUCF], place, origin];
        }else if(type(dict[valueUC]) === "string"){
            return [dict[valueUC], place, origin];
        }else if(type(dict[valueLCF]) === "string"){
            return [dict[valueLCF], place, origin];
        }else if(type(dict[valueLC]) === "string"){
            return [dict[valueLC], place, origin];
        };
        
        var term = tArray[origin].post;
        var isterm = new RegExp("([" + escapeChars('"') + escapeChars("'.,!`~+=_@#$%^?:;\|{}[]()") + "]+)", "gi");
        if((isterm.test(term)) || (place === (tArray.length-1))){
            if(failVal){
                return[ failVal, origin, origin];
            };
            return[ tArray[origin].token, origin, origin];
        };
        
        if(type(dict[value]) === "object"){
            return grammarLookup(dict[value], tArray[(place + 1)].token,
                                 tArray, (place + 1), origin, failVal);
        }else if(type(dict[valueUCF]) === "object"){
            return grammarLookup(dict[valueUCF], tArray[(place + 1)].token,
                                 tArray, (place + 1), origin, failVal);
        }else if(type(dict[valueUC]) === "object"){
            return grammarLookup(dict[valueUC], tArray[(place + 1)].token,
                                 tArray, (place + 1), origin, failVal);
        }else if(type(dict[valueLCF]) === "object"){
            return grammarLookup(dict[valueLCF], tArray[(place + 1)].token,
                                 tArray, (place + 1), origin, failVal);
        }else if(type(dict[valueLC]) === "object"){
            return grammarLookup(dict[valueLC], tArray[(place + 1)].token,
                                 tArray, (place + 1), origin, failVal);
        };
        
        if(!(dict.hasOwnProperty(value)) && !(place === origin)){
            if(failVal) {
                return[ failVal, origin, origin];
            };
            return[ tArray[origin].token, origin, origin];
        };
        
        
        if(failVal){
            return [failVal, place, origin];
        };
        return [value, place, origin];
        
    };
    
    var tokenize = function tokenize(str){
        var pre, token, post, mask;
       var gregex = new RegExp("(^|[\\W\\s_]+)" +  "(\\w+?)" + "(?=($|[[\\W\\s_]+))", "gi");
        var tokens = [];
        str = str.replace(gregex, function(match){
            pre      = RegExp.$1;
            token    = RegExp.$2;
            post     = RegExp.$3;
            mask     = caseMask(RegExp.$2);
            tokens.push({ pre: pre, token: token, post: post, caseMask: mask});
           return match;
        });
        return tokens;
    };
    var copyToken = function copyToken(old, newvalue){
        
        var newToken = {}, newBaseToken;
        newToken.pre = old.pre;
        newToken.post = old.post;
        
        if((newvalue) && (caseMask(newvalue) === "lc")){
            newBaseToken = applyCaseMask(newvalue, old.caseMask);
        } else {
            newBaseToken = newvalue
        }
        newToken.token = newBaseToken || old.token;
        newToken.caseMask = old.caseMask;
        return newToken;
    };
    
     var caseMask = function caseMask(str){
        var mask = "";
        if((str.toUpperCase() === str) && (str.length > 1) ){
            mask = "uc";
        }else if(str.toLowerCase() === str){
            mask = "lc";
        } else if(str.charAt(0).toUpperCase() === str.charAt(0)){
            mask = "ucf";
        } else if(str.charAt(0).toLowerCase() === str.charAt(0)){
            mask = "lcf";
        };
        return mask;
    };
    
   var applyCaseMask = function applyCaseMask(str, mask){
        if(mask === "uc"){ return str.toUpperCase()};
        if(mask === "lc"){ return str.toLowerCase()};
        if(mask === "ucf"){
            return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
        };
        if(mask === "lcf"){
            return str.charAt(0).toLowerCase() + str.substring(1).toLowerCase();
        };
        return str;
    };
    
    var escapeChars = function escapeChars(str){
        return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
    };
    
    var normalizeWS = function normalizeWS(str){
         return str.replace(/\s+/gi, ' ');
    };
    
    var type = function type(value) {
        var s = typeof value;
        if (s === 'object') {
            if (value) {
                if (typeof value.length === 'number' &&
                !(value.propertyIsEnumerable('length')) &&
                typeof value.splice === 'function') {
                       s = 'array';
                }
            } else {
                   s = 'null';
            };
        };
        return s;
    };
    

    return {
         config      : config
        ,ukifyText   : ukifyText
        ,moreifyText : moreifyText
        ,minifyText  : minifyText
        ,stripText   : stripText
        ,customSubs  : customSubs
        ,normalizeWS : normalizeWS
    };
}());

