/*
 * Editarea integration
 */

function highlightLines(linenrs, txtEditorId, style) {
	var lines = getLines(txtEditorId);
	for (var ix in linenrs) {
		var linenr = linenrs[ix] - 1; //lines counts from 1 arr from 0
		lines[linenr] = highlightLine(lines[linenr], style);
	}
	setLines(txtEditorId, lines);	
}
function highlightLine(line, style) {
	return "<span class=hiliteline style='" + style + "'>" + line + "</span>";
}
function setHtml(id, html) {
	var f=window.frames["frame_"+id];
    if(f){
    	var editArea = f.editArea;
    	var srcElem = f.document.getElementById("content_highlight");
    	srcElem.innerHTML = html;
	}	
}
function getHtml(id) {
	var f=window.frames["frame_"+id];
    if(f){
    	var editArea = f.editArea;
    	var srcElem = f.document.getElementById("content_highlight");
    	return srcElem.innerHTML;
	}
}
function getLines(id) {
	var html = getHtml(id);
	return html.split("\n");
}
function setLines(id, lines) {
	var html = lines.join("\n");
	setHtml(id, html);
}

// editor wrapper
function getCode(editorId) {
	return editAreaLoader.getValue(editorId);
}
function setCode(editorId, code) {
	return editAreaLoader.setValue(editorId, code);
}

/*
 * engine
 */

var ajaxErrorHandler;
$(document).ajaxError(function(event, request, settings){
   if (ajaxErrorHandler) ajaxErrorHandler(event, request, settings);
   ajaxErrorHandler = null;
});


function engine_translate(data, fun) {
	var wait = $("#wait"); 
	wait.css("display", "block");
	function errHandler(XMLHttpRequest, textStatus, errorThrown) {
		wait.css("display", "none");						 
		alert("An error has occurred communicating with the server. Sorry."); 					
	} 
	$.ajax({url:serviceUrl,data:data,dataType:"json",error:errHandler,success:fun,type:"POST"});	
}

function engine_suggest(source, offset, line, char, handler) {
	var request_data = {
			"source":source 
			,"service":"suggestions"
			,"offset":offset
			,"linePos":line
			,"charPos":char
		};
	function errHandler(XMLHttpRequest, textStatus, errorThrown) {						 
		data = null;  // silent fail					
	} 
	function success(result) {
		if (result==null) handler([]);
		else handler(result.suggestions);
	}
	$.ajax({url:serviceUrl,
		data:request_data,
		dataType:"json",
		error:errHandler,
		success:success,
		type:"POST",
		async:true});
}

/*
 * Extra editor UI (not part of the editarea module)
 */
var showCompilerSettings = false;
$(document).ready(function(){
	$("#compilerSettingsToggle").bind("click", toggleCompilerSettings)	
});

function toggleCompilerSettings() {
	showCompilerSettings = !showCompilerSettings;
	if (showCompilerSettings) {
		$("#compilerSettings").css("display", "block");
		$("#compilerSettingsToggle").text("Hide compiler settings")
	}
	else {
		 $("#compilerSettings").css("display", "none");
		 $("#compilerSettingsToggle").text("Show compiler settings");
	}
}

function translate(source, fun){
	var data = {"source":source, "service":"translate"};	
	// note: false will be interpreted as true on the server (bc. this is not JSON)
	if ($("#settings_semicolonInsertion").attr("checked")) data["compiler_setting_semicolon_insertion"] = true;
	engine_translate(data, fun);
}
	
function translateTxta(fromTxt, toTxt) {	
	var code = getCode(fromTxt);
	$("#msgArea").css("display", "none");
	beginTranslation();
	translate(code, function(data, status){	
		$("#wait").css("display", "none");		
        	displayResult(toTxt, data, fromTxt);
			sourceMap = data.sourceMap;
        });
}


function displayResult(toTxt, data, fromTxt) {	
	$("#msgArea").css("display", "block");
	if (data.success) {
		// we need to display js1 area *before* setting text
		// otherwise the editor will show it wrong!
		afterTranslated();
		setCode(toTxt, data.generatedCode)
		//toTxt.editor.syntaxHighlight();
		msg = "Compilation successful. "		
	} else {
		setCode(toTxt, "// No code generated.");
		msg = "Compilation failed. "
	}
	// hide output area (until next run)
	hideOutput();
	
	var tbl = $("#msgTbl");	
	if (data.messages.length>0) {
		msg += data.messages.length + " messages:";
		$("#msgTxt").text(msg);
		var msgLines = [];
		tbl.html("<tr><th>Line</th><th>Message</th></tr>"); // reset
		for (var ix in data.messages) {
			var msg = data.messages[ix];
			tbl.append("<tr class=" + msg.startLine +"><td class=line>" + msg.startLine + "</td><td>" + msg.description.replace("<", "&lt;") + "</td></tr>");
			msgLines.push(msg.startLine);
		}	
		highlightLines(msgLines, fromTxt, "background-color:yellow;background:url(/static/underline.gif) bottom repeat-x;");
		tbl.bind("click", function(ev) {tblClick(ev, fromTxt);});
	} else {
		msg += "No messages or warnings.";
		$("#msgTxt").text(msg);	
		tbl.html("<tr><th></th></tr>");
	}
}

function tblClick(ev, fromTxt) {
	if (ev.target.tagName=="TD") {
		var rw = ev.target.parentNode;
		var line = parseInt(rw.className);
		highlightLines([line], fromTxt, "background-color:yellow");
	}
}

function markRuntimeError(lineNo) {
	highlightLines([lineNo], 'js1', "background-color:red");
	for (var ix in sourceMap) {
		var item = sourceMap[ix]
		var genLine = item[0][0];
		if (genLine>=lineNo) {
			var srcLine = item[1][0];
			highlightLines([srcLine], 'esx', "background-color:red");
			break;
		}
	}
}


/** Running code */

function runIE(code, output) {
	try { 
		var result = eval(code);
		writeToOutput(result, output);
	} catch (e) {
		dump("Error:\n" + e.message, output);
	}
}

function runMoz(code, output) {
	//var result = eval(code); return;
	var errLinRef;
	// synch line numbers	
	try{var x=y;}catch(e){errLineRef=e.lineNumber;} try { var result = eval(code); // dont break this line
		writeToOutput(result, output);
	} catch (e) {
		if (e.lineNumber) {
			var codeLineNo = e.lineNumber-errLineRef + 1;
			markRuntimeError(codeLineNo)
		}
		dump("Error:\n" + e, output);
	}
}

function run(editorId) {
	var code = getCode(editorId);
	// show output area	
	var txta = $("#runOutputTxt");
	txta.text("");
	showOutputArea();
	
	// console implementation
	window.print = function(msg) {
		var str = "";
		for (var ix=0;ix<arguments.length; ix++) {
			if (ix>0) str += " ";
			str += arguments[ix];
		}
		writeToOutput(str, txta);
		//txta.text(txta.text() + str + "\n");
	}	
	if (document.all) {
		runIE(code, txta);
	} else {
		runMoz(code, txta);
	}
}
function writeToOutput(data, txta) {
	txta.text(txta.text() + data + "\n");
}

function dump(result, txta) {
	txta.text(result);
}
