
var Consonants = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"];
var Vowels = ["a", "e", "i", "o", "u", "y"];
var Conjuctions = ["for","and","nor","but","or","yet","so",
	"both","and","not","only","but","also","either","or","neither","nor","whether","or",
	"after","because","although","if","before","since","though","unless",
	"when","now","that","even","though","only","if",
	"while","as","whereas","whether","or","not",
	"since","in","order","that","while","even","if","until","so",
	"aboard","about","above","absent","across","after","against","along","alongside","amid","amidst",
	"among","amongst","around","as","aside","astride","at","athwart","atop","barring","before","behind",
	"below","beneath","beside","besides","between","betwixt","beyond","but","by","circa","concerning",
	"despite","down","during","except","excluding","failing","following","for","from","given","in","including",
	"inside","into","like","mid","minus","near","next","notwithstanding","of","off","on","onto","opposite","out",
	"outside","over","pace","past","per","plus","pro","qua","regarding","round","save","since",
	"than","through","thru","throughout","thruout","till","times","to","toward","towards","under",
	"underneath","unlike","until","up","upon","versus","vs","vs.","via","vice",
	"with","within","without","worth",
	"anent","anti","behither","betwixt","cum","ere","fornenst","fornent",
	"outwith","pro","qua","re","sans","unto","vis-à-vis",
	"concerning","considering","regarding","worth",
	"but","except","plus","save","ago","apart","aside","away","hence",
	"notwithstanding","on","through","withal"];

function in_array (needle, haystack, argStrict) {

    var key = '', strict = !! argStrict;
 
    if (strict) {
        for (key in haystack) {
            if (haystack[key] === needle) return true;
        }
    } else {
        for (key in haystack) {
		if (haystack[key] == needle) return true;
        }
    } 
    return false;
}

function trim (str, charlist) {
    var whitespace, l = 0, i = 0; str += '';
 
    if (!charlist) {        // default list
        whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
    } else {
        // preg_quote custom list
        charlist += '';        whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
    }
 
    l = str.length;
    for (i = 0; i < l; i++) {        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    } 
    l = str.length;
    for (i = l - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);            break;
        }
    }
 
    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}

function removeHyphen(st){
	st = st.replace(/[_-]/g, " ");
	return st;
}

function addslashes (str) {
    return (str + '').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0');
}

function is_numeric (mixed_var) {
    return (typeof(mixed_var) === 'number' || typeof(mixed_var) === 'string') && mixed_var !== '' && !isNaN(mixed_var);
}
function ucfirst (str) {
    str += '';
    var f = str.charAt(0).toUpperCase();
    return f + str.substr(1);
}

function change_title_case(str){
	var coordinating = ["and", "or", "from", "of", "for", "at", "to", "vs", "in", "nor"];

	var s = str.split(" ");
	var buffer = "";

	for(var i=0; i<s.length; i++) {
		var ss = s[i];
		if (coordinating.indexOf(ss) != -1) {
			buffer = buffer + ss + " ";
		} else {
			buffer = buffer + ucfirst(ss) + " ";  
		}
	}
	return trim(buffer);
}

function change_case(str, format, is_first){ // $is_first: is this first word of sentence?
	var coordinating = ["and", "or", "from", "of", "for", "at", "to", "vs", "in", "nor"];

	if (trim(format) == "") {return str;}

	if (!is_numeric(str[0]) && (str[0].toUpperCase() == str[0])) return str;

	if (is_numeric(format)) {
		if (is_first) { // change Title Case
			return ucfirst(str);
		} else {
			return str;
		}
	}

	if (format[0] == format[0].toLowerCase() && !is_numeric(format[0])) { 
		if (is_first) { // change Title Case
			return ucfirst(str);
		} else { // lowcase
			return str.toLowerCase();
		}
	}


	if ((format == format.toUpperCase()) && (format.length > 0)) { //  UPCASE
		return str.toUpperCase(); 
	}

	var fw = format.split(" ");
	i = 1; 

	while(i < fw.length) {
		if (!in_array(fw[i],coordinating) && (fw[i][0].toLowerCase() == fw[i][0]) && !is_numeric(fw[i][0])) break;
		i++;
	}
	
	if (i  < fw.length || fw.length == 1) { // First letter is UPCASE
		return ucfirst(str);
	} else {
		if (is_first) {
			return ucfirst(change_title_case(str));
		} else {
			 return change_title_case(str); 
		}
	}

}

function verb_forming(verb, tag) {

	var i, st, fverb;
	var l1, l2, l3;

	verb = verb.toLowerCase();

	verb = removeHyphen(verb);

	var s_verb = verb.split(" ");

	verb = s_verb[0];

	i = searchIrrVerb(verb);

	if (i == -1) { 
		l1 = verb.substr(verb.length - 1, 1);
		l2 = verb.substr(verb.length - 2, 1);
		l3 = verb.substr(verb.length - 3, 1);
	
		switch(tag) {
			case "VB": case "VBP":
				fverb = verb;
				break;

			case "VBD": case "VBN":
				switch (l1) {
					case "e": fverb = verb + "d"; break;
					case "y":
						if (Consonants.indexOf(l2) != -1) {
							fverb = verb.substr(0, verb.length - 1) + "ied";
						} else {
							fverb =  verb + "ed";
						}
						break;
					case "w": fverb = verb + "ed"; break;
					default: fverb = verb + "ed";
				}
				break;

			case "VBG": 
				switch (l1) {
					case "e": fverb = verb.substr(0, verb.length - 1) + "ing"; break;
					case "y": fverb = verb + "ing"; break;
					case "w": fverb = verb + "ing"; break;
					default: fverb = verb + "ing";
				}
				break;
			case "VBZ":
				switch (l1) {
					case "o": case "x": case "z": fverb = verb + "es";
						break;
					case "s":
						if (l2 == "s") {fverb = verb + "es";} else {fverb = verb + "s";}
						break;
					case "h":
						if ((l2 == "s") || (l2 == "c")) {fverb = verb + "es";} else {fverb = verb + "s";}
						break;
					case "y":
						if (Consonants.indexOf(l2) != -1) {
							fverb = verb.substr(0, verb.length - 1) + "ies";
						} else {
							fverb = verb + "s";
						}
						break;
					default:
						fverb = verb + "s";
				}
				break;
		}
	} else { 
		switch(tag) {
			case "VB": case "VBP": st = v[i].l; break;
			case "VBD": st = v[i].d; break;
			case "VBN": st = v[i].n; break;
			case "VBG": st = v[i].g; break;
			case "VBZ": st = v[i].z; break;
		}
		fverb = st;
	}
	if (s_verb.length > 1) {
		st = fverb;
		for(i=1; i < s_verb.length; i++) {
			st = st + " " + s_verb[i];
		}
		return st;
	} else {
		return fverb;
	}
}
function noun_fluralize(noun) {

	noun = noun.toLowerCase();
	noun = removeHyphen(noun);

	var s_noun = noun.split(" ");

	switch (s_noun.length) {
		case 1: break;
		case 2: if (Conjuctions.indexOf(s_noun[1]) != -1) {
				return s_noun[0] + " " + noun_fluralize(s_noun[1]);
			  } else {
				return noun_fluralize(s_noun[0]) + " " + s_noun[1];
			  }
		case 3: 
			switch (s_noun[1]) {
				case "and": case "or": case "nor":
					return noun_fluralize(s_noun[0]) + " " + s_noun[1] + " " + noun_fluralize(s_noun[2]);
					break;
				case "of": case "from": case "on": case "in": case "inside": case "within": 
				case "at": case "to": case "for": 
					return noun_fluralize(s_noun[0]) + " " + s_noun[1] + " " + s_noun[2];
					break;
			}
			break;
		case 4: return noun; 
	}

	var i = searchIrrNoun(noun);

	if (i == -1) { 
		l1 = noun.substr(noun.length - 1, 1);
		l2 = noun.substr(noun.length - 2, 1);
		l123 = noun.substr(noun.length - 3, 3);

		if (l123 == "man") return noun.substr(0, noun.length - 3) + "men";

		switch (l1) {
			case "s": case "z": case "x":
				fnoun = noun + "es"; 
				break;
			case "h":
				if ((l2 == "c") || (l2 == "s")) {fnoun = noun + "es";} else {fnoun = noun + "s";} 
				break;
			case "y":			
				if (Consonants.indexOf(l2) != -1) {
					fnoun = noun.substr(0, noun.length - 1) + "ies";
				} else {
					fnoun = noun + "s";
				}
				break;
			default:
				fnoun = noun + "s";
		}
	} else {
		return n[i].f;
	}
	return fnoun; 
}

function forming_syns(org, tag, syns, first, forming) {

	var s = syns.split("|");
	
	var buffer = "", fs;

	//alert(org + ":" + tag + ":" + syns + ":" + first + ":" + forming);

	for(var i=0; i< s.length; i++) {
		syns = s[i];
		
		switch(tag) {
			case "VB": case "VBD":case "VBG":case "VBN":case "VBP": case "VBZ":		
				if (forming) fs = verb_forming(syns, tag); else fs = syns;
				fs = change_case(fs, org, first);
				buffer +=  fs + " | ";
				break;
			case "NNS":
				if (forming) fs = noun_fluralize(trim(syns)); else fs = syns;
				fs = change_case(fs, org, first);
				buffer +=  fs + " | ";
				break;
			default:
				fs = change_case(syns, org, first);
				buffer +=  fs + " | ";
				break;
		}
	}

	return buffer.substr(0, buffer.length - 3);
}
function syns_unique(syns) {
	
	if (syns.length < 2) return "";

	var unique = new Array(), i, j=0, sbuff;
	var ss = syns.substr(1, syns.length - 2).split("}{");
	
	if (ss.length == 0) return "";

	unique[0] = ss[0];
	for(i=1; i < ss.length; i++) {
		if (unique.indexOf(ss[i]) == -1) {
			j++;
			unique[j] = ss[i];
		}
	}
	sbuff = unique[0];

	for(i=1; i < unique.length; i++) {
		sbuff += "}{" + unique[i];
	}
	return "{" + sbuff + "}";
}

function strpos (haystack, needle, offset) {
    var i = (haystack + '').indexOf(needle, (offset || 0));
    return i === -1 ? false : i;
}

// syn for single sentence <> syn.php for array of sentences
var syn_id = 0;
function create_syn(sentence) { 
	
	var special_chars = ["-LCB-","-LRB-", "-RCB-","-RRB-","-", "...", ".",",",":", '"', '“', "$", "'", "‘"];

	var i = 0;

	var buffer = "";
	var prev_tag = "";

	var fdata = sentence.split(" ");

	var idata = 0;

	while(idata < fdata.length) {

	   var data = fdata[idata];

	   if (data != ""){
		syn_id++;
		var s = data.split("/");
		s[0] = s[0].replace(/\\/g,"");
	
		switch(s.length){
		   case 1:
			//alert(1 + "\n" + data);	
			buffer = buffer + s[0].replace(/_/g, " ") + " ";
			break;
		   case 3:
			//alert(3 + "\n" + data);	
			var lastDT = "";

			switch(s[0]) {		
				case "$":
					next_tag = fdata[idata + 1].split("/") ;
					if (next_tag[1] == "CD") {buffer = buffer + s[0];} else {buffer = buffer + s[0] + " ";}
					break;			
				case "''": 
					buffer = trim(buffer) + '" ';
					break;
				case "'": 
					buffer = trim(buffer) + "' ";
					break;
				case '``': 
					buffer = buffer + '"';
					break;
				case "`":
					buffer = buffer + "'";
					break;
				case "-": case ":":
						buffer = buffer + s[0] + " ";
					break;
				case "...": case ".": case ",":
					buffer = trim(buffer) + s[0] + " ";
					break;
				case "'s":
					buffer = trim(buffer) + s[0] + " ";
					break;
				case "-LCB-": 
					buffer = buffer + "{";
					break;
				case "-LRB-": 
					buffer = buffer + "(";
					break;
				case "-RCB-": 
					buffer = trim(buffer) + "} ";
					break;
				case "-RRB-":	
					buffer = trim(buffer) + ") ";
					break;
				case "n't":	case "'ll":	case "'d": case "'ve": case "'s": case "?": case "!":
					buffer = trim(buffer) + s[0] + " ";
					break;
				case "a": case "an":					
					if (s[1] == "DT") {lastDT = s[1];}
					buffer = buffer + s[0] + " ";
					break;
				default:
					buffer = buffer + s[0] + " ";
					break;
			}
			prev_tag = s[1];
			break;
		   default:

			// Does/VBR/do/{do|perform}{to|make}/1
			var word = s[0]; 		// original words  
			var tag = s[1];  	// Tree Penn Tag
			var lemma = s[2]; 	// Lemma
			var sense_syns = s[3]; // list of syns by sense
			var best_sense = s[4]; // best sense index

			var sense = sense_syns.substr(1, sense_syns.length - 2).split("}{");

			var syns = "";
				
			word = removeHyphen(word);
				
			var sbuff = "{" + word + "}"; 

			var user_synonym = false, isense;

			var fsyns_array = new Array();
			fsyns_array[0] = word;
 			
			for(isense=0; isense < sense.length; isense++) {
				if (sense[isense] == "*") {user_synonym = true;	}

				var fsyns = forming_syns(word, tag, removeHyphen(sense[isense]), idata==0, !user_synonym);
			
				if (isense == best_sense - 1) syns = fsyns;

				if (!in_array(fsyns, fsyns_array)) {
					sbuff = sbuff + "#{" + fsyns + "}";
				}

				fsyns_array[isense + 1] = fsyns;
			}


			ssbuff = sbuff.split("#");
				
			sbuff = "";
			for(var issf=0; issf <  ssbuff.length; issf++) {sbuff += ssbuff[issf] + "#";}

			sbuff = sbuff.substr(0, sbuff.length -1);

			if ((idata != 0) && (word[0] == word[0].toUpperCase()) &&  (tag != "NNP") && (tag != "NNPS")) {
				syns = "";
			}
							
			if (tag=="JJS" || tag=="JJR" || tag=="RBR" || tag=="RBS" || syns=="") { 

				if (sbuff.indexOf("|") == -1) {
					buffer = buffer + word + " ";
				} else {
					buffer = buffer + '<span class="syn" id="s' + syn_id + '" pre="' + addslashes(sbuff) +'">' + word + '</span> ';
				}
			} else {

				var next_data = fdata[idata + 1];
				var next_s = next_data.split("/");

				var next_tag = next_s[1];

				if (tag == "NNP" || tag == "NNPS") {
					if (prev_tag == "NNP" || prev_tag == "NNPS" || next_tag == "NNP" || next_tag == "NNPS") {
						syns = "x"; // don't change							
					}
				} 
				if (syns == "x" ) {
					syns = "";
				} else {
					if (tag == "NNP" || tag == "NNPS") { // accepts Title syns only
						
						si = removeHyphen(syns).split("|");

						var syns_nnp = change_case(si[0], word, idata == 0);
						for(var z=1; z < si.length; z++) {
							si[z] = trim(si[z]);
							if (si[z][0] == si[z][0].toUpperCase()) { // Title case
									var si_case = change_case(si[z], word, idata == 0);
									syns_nnp = syns_nnp + " | " + si_case;
							}
						}
						syns = syns_nnp;
					}						
				}

				if (sbuff.indexOf("|") == -1) {
					buffer = buffer + word + ' ' ;	
				} else {
					if (syns == "") {
						//alert("break 1" + " " + data.substr(0,20));	
						buffer = buffer + '<span class="syn" id="s' + syn_id + '" pre="' + addslashes(sbuff) + '">' + word + '</span> ' ;
					} else {
						var si = syns.split("|");

						syns = si[0];

						// alert("break 2" + " " + data.substr(0,20));	

						for(var z=1; z < si.length; z++) {
							syns += "<span class=\"si\"> | " + trim(si[z]) + "</span>";
						}
						buffer = buffer + '<span class="syn" id="s' + syn_id + '" pre="' + addslashes(sbuff) + '">{' + syns + '}</span> ' ;
					} 
				}
			} 
			prev_tag = tag;
		}
		//alert(buffer);
	   }
	   idata++;
	}

	return buffer;
}

