/******************************************************************************
@owner: SVSi
@author: Arthur Johnson
@function: Evaluate User Scripts
*******************************************************************************/

	var clientvars = {};
	var servervars = {};
	
	var Controllers = {};

	function removeComments(script){
	
		var tscript = script;
		tscript = tscript.replace(/^\s*\n/gm, "");
		
		var tscriptarray = [];
		while (tscript.indexOf('\n') != -1){
			var tstring = tscript.substring(0,tscript.indexOf('\n')+1).trim();
			if (tstring.substring(0,2) != '//')	tscriptarray.push(tstring);
			tscript = tscript.substring(tscript.indexOf('\n')+1, tscript.length);
		}
		var tstring = tscript.trim();
		if (tstring.substring(0,2) != '//')	tscriptarray.push(tstring);
		var temptscr = '';
		for (var i=0; i<tscriptarray.length; i++){
			if (i != tscriptarray.length-1) temptscr += tscriptarray[i] + '\n';
			else temptscr += tscriptarray[i];
		}
		tscript = temptscr;
		
		return tscript;
		
	}
	
	function replaceAllWordLibrary(script){
		
		script = script.replaceAll(' disconnected', ' 0');
		script = script.replaceAll(' connected', ' 1');
		script = script.replaceAll(' off', ' 0');
		script = script.replaceAll(' on', ' 1');
		script = script.replaceAll(' false', ' 0');
		script = script.replaceAll(' true', ' 1');
		
		return script;
		
	}
	
	//function containsIf(script){ need to figure out way to make this work
		//find an if
		//go backward through script looking for [
		//go forward looking for ]
		//if neither found then return index of if
	//}
	
	function getLines(script){
		var tscript = script;
		var lines = [];
		while (tscript.indexOf('\n') != -1){
			var tline = tscript.substring(0, tscript.indexOf('\n'));
			if (tline !== "" && tline !== "\n") lines.push(tline);
			tscript = tscript.substring(tscript.indexOf('\n')+1, tscript.length);
		}
		if (tscript !== "" && tscript !== "\n") lines.push(tscript);
		return lines;
	}
	
	function combineLines(lines){
		var tscript = '';
		for (var i=0; i<lines.length; i++){
			tscript += lines[i];
		}
		return tscript;
	}
	
	function setServerVars(data, script, self, scriptorconditional){
		var nvars = jsonDeserialize(data);
		servervars = nvars;
		evalScript(script, self, scriptorconditional, true);
	}
	
	function removeJavascript(script){
		
		var tscript = script;
		var ttscript = script;
		
		while (ttscript.indexOf('<script>') != -1){
		
			if (ttscript.indexOf('</script>') != -1){
				var nscript = tscript.substring(
					ttscript.indexOf('<script>')+8,
					ttscript.indexOf('</script>')
				);
				var prenscript = '<script>';
				var postnscript = '</script>';
			}
			else {
				var nscript = tscript.substring(
					ttscript.indexOf('<script>')+8
				);
				var prenscript = '<script>';
				var postnscript = '';
			}
			
			var ttscript = ttscript.replace(prenscript+nscript+postnscript, '');
			
		}
		
		return ttscript;
		
	}
	
	function evalJavascript(script, self, bypass_security){

		var tscript = script;
		
		while (tscript.indexOf('<nCmd>') != -1){
	
			if (tscript.indexOf('</nCmd>') != -1){
				var nscript = tscript.substring(
					tscript.indexOf('<nCmd>')+6,
					tscript.indexOf('</nCmd>')
				);
				var prenscript = '<nCmd>';
				var postnscript = '</nCmd>';
			}
			else {
				var nscript = tscript.substring(
					tscript.indexOf('<nCmd>')+6
				);
				var prenscript = '<nCmd>';
				var postnscript = '';
			}
			
			var tscript = tscript.replace(prenscript+nscript+postnscript, 
				"nCmdAsync('"+nscript.replace(/[\r\n]/g, "\\\n")+"');");

		}
		//console.log('self',self);
		if (bypass_security === true && 0){
			window.panel = project.currentpanel;
			window.buttons = project.currentpanel.buttons;
			window.canvas = canvas1;
			window.createElement = document.createElement;
			eval(tscript);
		}
		else {
			var global = {
				nCmd: nCmd,
				nCmdAsync: nCmdAsync,
				require: require,
				project: project,
				panel: project.currentpanel,
				buttons: project.currentpanel.buttons,
				canvas: canvas1,
				Image: Image,
				setInterval: setInterval,
				createElement: document.createElement,
				gotopanel: gotopanel,
				responses: responses,
				saveGlobals: saveGlobals,
				tweencss: tweencss,
				getButton: getButton,
				asciiToHex: asciiToHex,
				hexToAscii: hexToAscii,
				subPanel: subPanel,
				tcpopen: tcpopen,
				tcpsend: tcpsend,
				tcpclose: tcpclose,
				tcpclient: tcpclient,
				udpclient: udpclient,
				self: self,
				$: $,
			}

			for (var property in globalvars) {
				if (globalvars.hasOwnProperty(property)) {
					global[property] = globalvars[property];
				}
			}
			
			for (var property in Controllers) {
				if (Controllers.hasOwnProperty(property)) {
					global[property] = Controllers[property];
				}
			}

			sandbox(tscript, global);
		}
		
		return tscript;
		
	}
	
	function evalScript(script, self, scriptorconditional, override){
	
		if (script.indexOf('$$') != -1 && !override){
			queryDB({
				opts: {id: project.id, query: 'getdata'},
				callback: setServerVars,
				script: script,
				self: self,
				scriptorconditional: scriptorconditional
			}, "servervars.php");
			return;
		}
	
		if (undef(script) || script === '') return;

		var tscript = script;
		
		//evaluate and remove javascript
			tscript = evalJavascript(tscript, self);
		
		//remove blanks
			tscript = tscript.replace(/^\s*\n/gm, "");
		
		//remove commented out lines
			tscript = removeComments(tscript);
			
		//todo: remove long commented sections ie: /* */
			//tscript = removeLongComments(tscript);
		
		//replace all words that equate to true/false
			tscript = replaceAllWordLibrary(tscript);
		
		//check for an if keyword
		if (tscript.toLowerCase().indexOf('if ') == -1){
			sendScript(tscript, self);
			return;
		}
		
		var comparescript = tscript;
		
		var tokenizer = tscript;
		var statements = [];
		
		//tokenize script into if sections
		while (tokenizer.toLowerCase().indexOf('if ') != -1){
		
			var tsend = tokenizer.substring(0, tokenizer.toLowerCase().indexOf('if '));
			sendScript(tsend);
			
			if (tsend !== '//') tokenizer = tokenizer.substring(tokenizer.toLowerCase().indexOf('if '), tokenizer.length);
			
			var endindex = tokenizer.length;
			var simplecheck = tokenizer.substring(tokenizer.toLowerCase().indexOf('if')+2, tokenizer.length);
			
			if (simplecheck.toLowerCase().indexOf('if ') != -1) endindex = simplecheck.toLowerCase().indexOf('if ')+2;
			
			statements.push(tokenizer.substring(0, endindex));
			comparescript = comparescript.replace(tokenizer.substring(0, endindex), '');
			tokenizer = tokenizer.substring(endindex, tokenizer.length);
			
		}
		
		var tokenizer = tscript;
		var ifelsestatements = [];
		
		for (var i=0; i<statements.length; i++){
			if (statements[i].indexOf('else') != -1){
				ifelsestatements.push({
					ifstring: statements[i].substring(0, statements[i].indexOf('else')),
					iflines: [],
					elsestring: statements[i].substring(statements[i].indexOf('else'), statements[i].length),
					elselines: []
				});
			}
			else {
				ifelsestatements.push({
					ifstring: statements[i],
					iflines: [],
					elsestring: false,
					elselines: false
				});
			}
		}
		
		for (var i=0; i<ifelsestatements.length; i++){
		
			if (ifelsestatements[i].ifstring.indexOf("{") != -1 && ifelsestatements[i].ifstring.indexOf("}") != -1){
			
				var tifstatement = ifelsestatements[i].ifstring.substring(
					ifelsestatements[i].ifstring.indexOf("{")+1,
					ifelsestatements[i].ifstring.indexOf("}")
				);
				
				evalScript(ifelsestatements[i].ifstring.substring(
					ifelsestatements[i].ifstring.indexOf("}")+1,
					ifelsestatements[i].ifstring.length
				), self, scriptorconditional, true);
			
				while (tifstatement.indexOf('\n') != -1){
					var tline = tifstatement.substring(0, tifstatement.indexOf('\n'));
					if (tline !== '' && tline != '\n') ifelsestatements[i].iflines.push(tline);
					tifstatement = tifstatement.substring(tifstatement.indexOf('\n')+1, tifstatement.length);
				}
				
				if (tifstatement.trim() != '' && tifstatement.trim() != '\n')
						ifelsestatements[i].iflines.push(tifstatement.trim());
				
				ifelsestatements[i].ifstring = 
					ifelsestatements[i].ifstring.substring(0, ifelsestatements[i].ifstring.indexOf("{"));
			
			}
			else {

				ifelsestatements[i].iflines.push(
					ifelsestatements[i].ifstring.substring(
						ifelsestatements[i].ifstring.lastIndexOf(')')+1, 
						ifelsestatements[i].ifstring.length
					)
				);
				
				ifelsestatements[i].ifstring = 
					ifelsestatements[i].ifstring.substring(0, ifelsestatements[i].ifstring.indexOf(")")+1);
			
			}
			
			if (ifelsestatements[i].elsestring){
			
				if (ifelsestatements[i].elsestring.indexOf("{") != -1 && ifelsestatements[i].elsestring.indexOf("}") != -1){
			
					var telsestatement = ifelsestatements[i].elsestring.substring(
						ifelsestatements[i].elsestring.indexOf("{")+1,
						ifelsestatements[i].elsestring.indexOf("}")
					);
					
					evalScript(ifelsestatements[i].elsestring.substring(
						ifelsestatements[i].elsestring.indexOf("}")+1,
						ifelsestatements[i].elsestring.length
					), self, scriptorconditional, true);
				
					while (telsestatement.indexOf('\n') != -1){
						var tline = telsestatement.substring(0, telsestatement.indexOf('\n'));
						if (tline !== '' && tline != '\n') ifelsestatements[i].elselines.push(tline);
						telsestatement = telsestatement.substring(telsestatement.indexOf('\n')+1, telsestatement.length);
					}
					
					if (telsestatement.trim() != '' && telsestatement.trim() != '\n')
						ifelsestatements[i].elselines.push(telsestatement.trim());
					
					ifelsestatements[i].elsestring = 
						ifelsestatements[i].elsestring.substring(0, ifelsestatements[i].elsestring.indexOf("{"));
				
				}
				else{
				
					ifelsestatements[i].elselines.push(
						ifelsestatements[i].elsestring.substring(
							ifelsestatements[i].elsestring.indexOf('else')+5, 
							ifelsestatements[i].elsestring.length
						)
					);
					
					ifelsestatements[i].elsestring = 'else ';
				
				}
			
			}
		
		}
		
		for (var i=0; i<ifelsestatements.length; i++){
			
			var ifstring = ifelsestatements[i].ifstring = ifelsestatements[i].ifstring.replace(/\s/g,'');
			
			var sl1 = ifstring.replace(/\s/g,'');  
			
			if (sl1.substring(0,2) == '//') sl1 = '';
			
			var tstr1 = sl1;
			
			while (tstr1.indexOf(")") != -1){
			
				var tstr2 = tstr1;
			
				tstr2 = tstr2.substring(0, tstr2.indexOf(")")+1);
				var tstr12ndex = -1, ijk = tstr2.length-1;
				while (ijk > -1){
					
					if (tstr2.charAt(ijk) == "("){
						tstr2index = ijk;
						break;
					}
					ijk--;
				}
				
				var tstr3 = tstr2.substring(tstr2index, tstr2.length);
				tstr2 = tstr2.substring(tstr2index+1, tstr2.length-1);
				
				var t1 = evalBooleanStatement(tstr2, self); 
				tstr1 = tstr1.replace(tstr3, t1);
				
			}
			
			var ifresult = tstr1.replace('if','');
			
			if (ifresult === 1 || ifresult === '1'){

				if (scriptorconditional === 'script'){
					
					var combinedscript = '';
					for (var k=0; k<ifelsestatements[i].iflines.length; k++){

						if (ifelsestatements[i].iflines[k].indexOf('this') != -1 ||
							ifelsestatements[i].iflines[k].indexOf('$') != -1 ||
							ifelsestatements[i].iflines[k].indexOf('Button-') != -1 ||
							ifelsestatements[i].iflines[k].indexOf('Widget-') != -1){
								evalSetStatement(ifelsestatements[i].iflines[k], self);
						}
						else combinedscript += ifelsestatements[i].iflines[k] + '\n';
					}
					sendScript(combinedscript, self);
				}
				if  (scriptorconditional === 'conditional'){

					for (var k=0; k<ifelsestatements[i].iflines.length; k++){
						evalSetStatement(ifelsestatements[i].iflines[k], self);
					}
				}
			}
			else if (ifelsestatements[i].elsestring){
				if (scriptorconditional === 'script'){
					var combinedscript = '';
					for (var k=0; k<ifelsestatements[i].elselines.length; k++){
						if (ifelsestatements[i].elselines[k].indexOf('this') != -1 ||
							ifelsestatements[i].elselines[k].indexOf('$') != -1 ||
							ifelsestatements[i].elselines[k].indexOf('Button-') != -1 ||
							ifelsestatements[i].elselines[k].indexOf('Widget-') != -1){
								evalSetStatement(ifelsestatements[i].elselines[k], self);
						}
						else combinedscript += ifelsestatements[i].elselines[k] + '\n';
					}
					sendScript(combinedscript, self);
				}
				if (scriptorconditional === 'conditional'){
					for (var k=0; k<ifelsestatements[i].elselines.length; k++){
						evalSetStatement(ifelsestatements[i].elselines[k], self);
					}
				}
			}
			
		}
		
		if (scriptorconditional === 'script'){
			var finallines = getLines(comparescript);
			var finalscript = '';
			for (var i=0; i<finallines.length; i++){
				if (finallines[i].indexOf('this') != -1 ||
					finallines[i].indexOf('$') != -1 ||
					finallines[i].indexOf('Button-') != -1 ||
					finallines[i].indexOf('Widget-') != -1){
						evalSetStatement(finallines[i], self);
				}
				finalscript += finallines[i];
			}
			sendScript(finalscript, self);
		}
	}
	
	function checkStateStatement(str){
		var tstr = str;
		var tstra = tstr.substring(0,nindexOf(tstr,"=",1));
		var tstrb = tstr.substring(nindexOf(tstr,"=",1)+1,tstr.length);
		if (tstra == "this" && tstrb == "state1") return 0;
		else if (tstra == "this" && tstrb == "state2") return 1;
		else if (tstra == "this" && tstrb == "hidden") return -1;
		else return false;
	}
	
	function evalSetStatement(st, self){
	
		if (st.indexOf('$$') != -1){
			var tst = st;
			var tsta = ((tst.substring(0, tst.indexOf('='))).trim()).replace('$$','');
			var tstb = (tst.substring(tst.indexOf('=')+1, tst.length)).trim();
			
			servervars[tsta] = tstb;
			
			queryDB({opts: {id: project.id, query: 'setdata'}, data: jsonSerialize(servervars)}, "servervars.php");
			return;
		}
		else if (st.indexOf('$') != -1){
			var tst = st;
			var tsta = ((tst.substring(0, tst.indexOf('='))).trim()).replace('$','');
			var tstb = (tst.substring(tst.indexOf('=')+1, tst.length)).trim();
			
			clientvars[tsta] = tstb;
			
			return;
		}
	
		var tst = st;
		var tsta = tst.substring(0, tst.indexOf('='));
		var tstb = tst.substring(tst.indexOf('=')+1, tst.length);
			
		var tsta1 = tsta.substring(0, tsta.lastIndexOf('.'));
		var tsta2 = tsta.substring(tsta.lastIndexOf('.')+1, tsta.length);
		
		tstb = tstb.trim();
		switch (tstb){
			case 'state1':
				tstb = 0;
				break;
			case 'state2':
				tstb = 1;
				break;
			case 'hidden':
				tstb = -1;
				break;
			default:
				break;
		}
		
		var nitem = false;
		
		tsta1 = tsta1.trim();
		
		if (tsta1 == "this"){
			nitem = self;
		}
		else {
			for (var bind=0; bind<project.currentpanel.buttons.length; bind++){
				if (tsta1 == project.currentpanel.buttons[bind].id)
					nitem = project.currentpanel.buttons[bind];
			}
			for (var wind=0; wind<project.currentpanel.widgets.length; wind++){
				if (tsta1 == project.currentpanel.widgets[wind].id)
					nitem = project.currentpanel.widgets[wind];
			}
		}
		
		if (nitem) {
			switch (tsta2.trim()){
				case 'state':
					nitem.setState(tstb);
					break;
				case 'text':
					nitem.textNode.innerHTML = tstb.replaceAll("\"", '');
					break;
				case 'fontcolor':
					nitem.textNode.style.color = tstb.replaceAll("\"", '');
					break;
				case 'fontsize':
					nitem.textNode.style.fontSize = tstb.replaceAll("\"", '') + 'px';
					var theight = ($(nitem.element).outerHeight()/2) - ($(nitem.textNode).outerHeight()/2);
					$(nitem.textNode).css('top', theight + 'px');
					break;
				case 'fontstyle':
					nitem.textNode.style.fontFamily = tstb.replaceAll("\"", '');
					break;
				case 'width':
					var oldwidth = $(nitem.element).outerWidth()/2;
					var newwidth = parseFloat(tstb.replaceAll("\"", ''))/2;
					var oldleft = parseFloat(nitem.element.style.left);
					var newleft = oldleft + (oldwidth - newwidth);
					
					nitem.element.style.width = tstb.replaceAll("\"", '') + 'px';
					nitem.element.style.left = newleft + 'px';
					
					var theight = ($(nitem.element).outerHeight()/2) - ($(nitem.textNode).outerHeight()/2);
					$(nitem.textNode).css('top', theight + 'px');
					break;
				case 'height':
					var oldheight = $(nitem.element).outerHeight()/2;
					var newheight = parseFloat(tstb.replaceAll("\"", ''))/2;
					var oldtop = parseFloat(nitem.element.style.top);
					var newtop = oldtop + (oldheight - newheight);
					
					nitem.element.style.height = tstb.replaceAll("\"", '') + 'px';
					nitem.element.style.top = newtop + 'px';
					
					var theight = ($(nitem.element).outerHeight()/2) - ($(nitem.textNode).outerHeight()/2);
					$(nitem.textNode).css('top', theight + 'px');
					break;
				case 'value':
					if (nitem.script[0]) nitem.script[0].replaceAll(nitem.id+'.value', nitem.value);
					if (nitem.script[1]) nitem.script[1].replaceAll(nitem.id+'.value', nitem.value);
					break;
				default:
					break;
			}
		}
		
	}
	
	function evalBooleanStatement(st, self){
		if (st === 1 || st === "1") return 1;
		if (st === 0 || st === "0") return 0;
		
		var finaloparray = [];
		var finaltokenarray = [];
		
		var tstate = st;
		
		var starray1 = tstate.split('&&');
		var starray2 = []; //token list
		for (var stind=0; stind<starray1.length; stind++){
			var starray3 = starray1[stind].split('||');
			for (var stind2=0; stind2<starray3.length; stind2++){
				starray2.push(starray3[stind2]);
			}
		}
		
		var starray4 = [];
		for (var tokind=0; tokind<starray2.length; tokind++){
			starray4.push(evalSingleBooleanStatement(starray2[tokind], self));
		}
		
		var fstring = st;
		for (var find=0; find<starray4.length; find++){
			fstring = fstring.replace(starray2[find], starray4[find]);
		}
		
		if (fstring.indexOf('id') != -1){
			
		}

		return eval(fstring);		
	}
	
	function evalSingleBooleanStatement(st, self){
	
		if (st === 1 || st === "1") return 1;
		if (st === 0 || st === "0") return 0;
		
		if (st.indexOf("==")){
			var yes = 1;
			var no = 0;
		}
		else if (st.indexOf("==")){
			var no = 1;
			var yes = 0;
		}
		else return 0;
		
		var eqind = st.indexOf("==");
		var h1 = st.substring(0, eqind);
		var h2 = st.substring(eqind+2, st.length);
		h2 = h2.replaceAll('"', '');
		h2 = h2.replaceAll("'", '');
		switch (h2){
			case 'state1':
				h2 = 0;
				break;
			case 'state2':
				h2 = 1;
				break;
			case 'hidden':
				h2 = -1;
				break;
			default:
				break;
		}
		
		if (h1.indexOf('$$') != -1){
			var t1 = h1.replace('$$','').replace('[','').replace(']','').trim();
			if (servervars[t1] == h2.trim()) return yes;
			else return no;
		}
		else if (h1.indexOf('$') != -1){
			var t1 = h1.replace('$','').replace('[','').replace(']','').trim();
			if (clientvars[t1] == h2.trim()) return yes;
			else return no;
		}
		
		for (var property in clientvars)
			if (clientvars.hasOwnProperty(property))
				h2 = h2.replaceAll('$'+property, clientvars[property]);

		for (var property in servervars)
			if (servervars.hasOwnProperty(property))
				h2 = h2.replaceAll('$$'+property, servervars[property]);
		
		var dotind = h1.lastIndexOf(".");
		var h1a = h1.substring(0, dotind);
		var h1b = h1.substring(dotind+1, h1.length);
		
		var nitem = false;
		
		if (h1a.indexOf("]") != -1){

			var tname = h1a.substring(h1a.indexOf("[")+1, h1a.indexOf("]"));
			
			for (var mlind=0; mlind<monitorlist.length; mlind++){
				if (tname == monitorlist[mlind].ip)
					nitem = monitorlist[mlind];	
				//todo: check mac address and name
				//need to add to status message in webSocketServer.c
			}
		}
		
		if (h1a == "this"){
			nitem = self;
		}
		else {
			for (var bind=0; bind<project.currentpanel.buttons.length; bind++){
				if (h1a == project.currentpanel.buttons[bind].core.id)
					nitem = project.currentpanel.buttons[bind];
			}
			for (var wind=0; wind<project.currentpanel.widgets.length; wind++){
				if (h1a == project.currentpanel.widgets[wind].core.id)
					nitem = project.currentpanel.widgets[wind];
			}
		}
		
		switch (h1b){
			case 'state':
				if (nitem.currentstate == h2) return yes;
				else return no;
				break;
			case 'value':
				if (nitem.value == h2) return yes;
				else return no;
				break;
			case "resolution":
				if (nitem.resolution == h2) return yes;
				else return no;
				break;
			case "dvioff":
				if (nitem.dvioff == h2) return yes;
				else return no;
				break;
			case "scalerbypass":
				if (nitem.scalerbypass == h2) return yes;
				else return no;
				break;
			case "dvistatus":
				if (nitem.dvistatus == h2) return yes;
				else return no;
				break;
			case "playmode":
				if (nitem.playmode == h2) return yes;
				else return no;
				break;
			case "audiostate":
				if (nitem.audiostate == h2) return yes;
				else return no;
				break;
			case "stream":
				if (nitem.stream == h2) return yes;
				else return no;
				break;
			case "audiostream":
				if (nitem.audiostream == h2) return yes;
				else return no;
				break;
			case "playlist":
				if (nitem.playlist == h2) return yes;
				else return no;
				break;
			case "clrspccor":
				if (nitem.clrspccor == h2) return yes;
				else return no;
				break;
			default:
				break;
		}

		return 0;

	}
