/*
 *
 * Copyright (C) 2009 EmbedOne.
 * Contact: EmbedOne Software Information (info@embedone.com)
 *
 * Commercial Usage
 * Licensees holding valid EmbedOne Commercial licenses may use this file
 * in accordance with the EmbedOne Commercial License Agreement provided
 * with the Software or, alternatively, in accordance with the terms
 * contained in a written agreement between you and EmbedOne.
 *
 * GNU General Public License Usage
 * Alternatively, this file may be used under the terms of the GNU
 * General Public License version 3.0 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.  Please review the following information to
 * ensure the GNU General Public License version 3.0 requirements will be
 * met: http://www.gnu.org/copyleft/gpl.html.
 *
 * If you are unsure which license is appropriate for your use, please
 * contact the EmbedOne sales department at sales@embedone.com.
 *
 */

// NOTE: currently web ui can process only a single outstanding call

// =================== 
//   Initialization
// ===================


// mInitApp is called on load and should open the config screen
function mInitApp(){
	mSetWrapper( numConstWrapperStateConnect );
}

// Do cookies
// grabbed from http://www.quirksmode.org/js/cookies.html
function mCreateCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function mReadCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function mEraseCookie(name) {
	mCreateCookie(name,"",-1);
}
// end grub

// ====================
//  Screen handling
// ====================
var numConstWrapperStateConnect = 1;
var numConstWrapperStateWaiting = 2;
var numConstWrapperStateMain = 3;

function mSetWrapper( dWrapperState ){
	if( dWrapperState == numConstWrapperStateConnect ){
		document.getElementById("wrap").innerHTML = txtWrapConnect;
		mSetConnectValues();
	}else if( dWrapperState == numConstWrapperStateWaiting ){
		document.getElementById("wrap").innerHTML = txtWrapWaiting;	
	}else if( dWrapperState == numConstWrapperStateMain ){
		document.getElementById("wrap").innerHTML = txtWrapMain;
		document.getElementById("iInfoDevice").innerHTML = oVersionInfo.iHost + " ("+oConnect.iAddress+")";
		document.getElementById("iInfoSystem").innerHTML = oVersionInfo.iSysVersion;
		document.getElementById("iInfoEMI").innerHTML = oVersionInfo.iEMIVersion;
		document.getElementById(vCurrentContainer).className = "current";
		mSetContainer( vCurrentContainer );
	}else{
		dbAlert( "mSetWrapper : BAD STATE" + dWrapperState );			
	}
}

var txtContainerStateConfig = "iLiConf";
var txtContainerStateStat = "iLiStat";
var txtContainerStateSys = "iLiSys";
var txtContainerStateUtil = "iLiUtil";
var txtContainerStateHelp = "iLiHelp";
var txtContainerStateBug = "iLiBug";
var txtContainerStateCustom = "iLiCustom";

var vCurrentContainer = txtContainerStateConfig;

function mSetContainer( dContainerState ){
	// TODO remove next line
		document.getElementById("title").innerHTML = dContainerState;
	
	if( dContainerState == txtContainerStateConfig ){
		document.getElementById("subnav").innerHTML = objTxtConfiguration.iSubNav;
		//document.getElementById("content").innerHTML = objTxtConfiguration.iContent;
		document.getElementById("actions").innerHTML = objTxtConfiguration.iActions;
		document.getElementById("footer").innerHTML = objTxtConfiguration.iFooter;
		
		vCurrentContainer = txtContainerStateConfig;
	}
	else if( dContainerState == txtContainerStateStat ){
		vCurrentContainer = txtContainerStateStat;
		document.getElementById("title").innerHTML = objTxtStat.iTitle;
		document.getElementById("subnav").innerHTML = objTxtStat.iSubNav;
		document.getElementById("content").innerHTML = objTxtStat.iContent;
		document.getElementById("actions").innerHTML = objTxtStat.iActions;
		document.getElementById("footer").innerHTML = objTxtStat.iFooter;
	}
	else if( dContainerState == txtContainerStateSys ){
			vCurrentContainer = txtContainerStateSys;
	}
	else if( dContainerState == txtContainerStateUtil ){
		vCurrentContainer = txtContainerStateUtil;
	}
	else if( dContainerState == txtContainerStateHelp ){
		vCurrentContainer = txtContainerStateHelp;
	}
	else if( dContainerState == txtContainerStateBug ){
		vCurrentContainer = txtContainerStateBug;
		document.getElementById("title").innerHTML = objTxtBug.iTitle;
		document.getElementById("subnav").innerHTML = objTxtBug.iSubNav;
		document.getElementById("content").innerHTML = objTxtBug.iContent;
		document.getElementById("actions").innerHTML = objTxtBug.iActions;
		document.getElementById("footer").innerHTML = objTxtBug.iFooter;
		vCurrentContainer = txtContainerStateBug;
	}
	else if( dContainerState == txtContainerStateCustom ){
		vCurrentContainer = txtContainerStateBug;
		document.getElementById("title").innerHTML = objTxtRawJsonP.iTitle;
		document.getElementById("subnav").innerHTML = objTxtRawJsonP.iSubNav;
		document.getElementById("content").innerHTML = objTxtRawJsonP.iContent;
		document.getElementById("actions").innerHTML = objTxtRawJsonP.iActions;
		document.getElementById("footer").innerHTML = objTxtRawJsonP.iFooter;
		if(vLastRawRequest == null || vLastRawRequest == ""){
			document.getElementById("data_request").value = '{"EMI-RPC":"1.0", "method":"emi.sys.version", "params":{"session":"'+vRpcSession+'"}, "id":'+vRpcId+'}';
		}else{
			document.getElementById("data_request").value = vLastRawRequest;
		}
		vCurrentContainer = txtContainerStateCustom;
	}
	else{
		dbAlert( "mSetContainer : BAD STATE" + dContainerState );			
		return;
	}
	mAdjustSubnavs();
}


// ==============================
//  Connect handling
// ==============================

// connect data
var oConnect = new oConnectObject();

function oConnectObject(){
	//this.iAddress = "http://host:port/path";
	//this.iAddress = "http://192.168.1.2:2001";
	//this.iUsername = "admin";
	//this.iPassword = "password";
	this.iAddress = mReadCookie("iConnectAddress");
	if( this.iAddress == null ){
		this.iAddress = "";
	}
	this.iUsername = mReadCookie("iConnectUser");
	if( this.iUsername == null ){
		this.iUsername = "";
	}
	this.iPassword = mReadCookie("iConnectPass");
	if( this.iPassword == null ){
		this.iPassword = "";
	}
}

// connect data
var oVersionInfo = new oVersionInfoObject();

function oVersionInfoObject(){
	this.iHost = "undetected";
	this.iSysVersion = "undetected";
	this.iEMIVersion = "0.9";
}

 
// mConnect will do the following
// 1. remember the settings
// 2. post waiting screen
// 3. send the jsonp request for session
// 4. if received a successful session id it will open the interface
// 5. if error it will alert for error and go back to the connect screen


// mSetConnectValues assigns the values of the internal variables to the gui objects
function mSetConnectValues(){
	document.getElementById("iConnectAddress").value = oConnect.iAddress;
	document.getElementById("iConnectUsername").value = oConnect.iUsername;
	document.getElementById("iConnectPassword").value = oConnect.iPassword;
}

// whenever connect is pressed, we need to save the entered values for the future use
function mSaveConnectValues(){
	oConnect.iAddress = document.getElementById("iConnectAddress").value;
	oConnect.iUsername = document.getElementById("iConnectUsername").value;
	oConnect.iPassword = document.getElementById("iConnectPassword").value;

	mCreateCookie("iConnectAddress",oConnect.iAddress, 10);
	mCreateCookie("iConnectUser",oConnect.iUsername, 10);
	mCreateCookie("iConnectPass",oConnect.iPassword, 10);
}

//
// handling the connect command
//
function mDoConnect(){
	// saving data
	mSaveConnectValues();
	// go to waiting state display
	mSetWrapper( numConstWrapperStateWaiting );
	// alert("before" );
	mEmiRpcSend( "emi.session.start", {"user":oConnect.iUsername,"password":oConnect.iPassword} , "mDoConnect_Complete");
}

var txtHostnameKey = "hostname.hostname";


function mDoConnect_Complete(dResult){
	if( dResult == null ){
		alert( "Error Connecting! Try Again!");
		mSetWrapper( numConstWrapperStateConnect );
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateConnect );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
	
		if( dResult.result == null ){
			alert("Error! Malformed result!");		
			mSetWrapper( numConstWrapperStateConnect );
			return;
		}
		vRpcSession = dResult.result.session;
		
		// we need to retrieve the information about the system before displaying anything
		
		// information is now retrieved or missing.
		// TODO: if it is missing, its not a critical error for now
		//mEmiRpcSend( "emi.conf.get", {"key":txtHostnameKey} , "mConnecting_RequestHostnameComplete");
		mSendStat("hostname.hostname", "mConnecting_RequestHostnameComplete");
		// now we continue in mConnecting_RequestHostnameComplete
	}
}

// REQUESTING THE Host name info 
function mConnecting_RequestHostnameComplete(dResult){
//vRpcId = 99;
	//alert("response"+mSimpleJSONStringify(dResult));
	if( dResult == null ){
		//alert("Host result 0");
		oVersionInfo.iHost = "<i>unknown</i>";
		//mSetWrapper( numConstWrapperStateMain );
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {				
				// TODO: could be a warning or something. Not handling now.
			}
		}
	
		if( dResult[0] != null ){
			if( dResult[0].key == txtHostnameKey ){		
				oVersionInfo.iHost = dResult[0].value;

			}else{
				alert("Didnt receive a correct hostname for request!");
					mSetWrapper( numConstWrapperStateConnect );

			}
		}else{
				alert("Didnt receive a correct RESULT for hostname request!");		
				mSetWrapper( numConstWrapperStateConnect );
		}
	}

	// getting the system varsion info
//	mEmiRpcSend( "emi.sys.version", null, "mConnecting_RequestVersionComplete");		
	mSendStat("osinfo.name", "mConnecting_RequestVersionComplete");
}


// REQUESTING THE Version info 
function mConnecting_RequestVersionComplete(dResult){
	if( dResult == null ){
		// do nothing, its a non-critical error
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
	
		if( dResult[0] != null ){
			if( dResult[0].key == "osinfo.name" ){		
				oVersionInfo.iSysVersion = dResult[0].value;

			}else{
				alert("Didnt receive a correct hostname for request!");
				mSetWrapper( numConstWrapperStateConnect );
			}
		}else{
				alert("Didnt receive a correct RESULT for hostname request!");		
				mSetWrapper( numConstWrapperStateConnect );
		}
	}
			
	// continuing to the next step, hardcodded for now
//	oVersionInfo.iEMIVersion = "1.0";
	mSendStat("osinfo.version", "mConnectiong_LastVersion");
	
	// lets display the Logo+Info 
	//alert("Progress " + vRpcSession);
	
	//mConfig_RequestNewTree();
	//mSetWrapper( numConstWrapperStateMain );
}

function mConnectiong_LastVersion( dResult ){
	if( dResult == null ){
		// do nothing, its a non-critical error
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
	
		if( dResult[0] != null ){
			if( dResult[0].key == "osinfo.version" ){		
				oVersionInfo.iSysVersion = oVersionInfo.iSysVersion + " " + dResult[0].value;

			}else{
				alert("Didnt receive a correct hostname for request!");
				mSetWrapper( numConstWrapperStateConnect );
			}
		}else{
				alert("Didnt receive a correct RESULT for hostname request!");		
				mSetWrapper( numConstWrapperStateConnect );
		}
	}
			
	
	mSendStat("osinfo.platform", "mConnectiong_LastPlatform");
	//mSetWrapper( numConstWrapperStateMain );

}


function mConnectiong_LastPlatform( dResult ){
	if( dResult == null ){
		// do nothing, its a non-critical error
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
	
		if( dResult[0] != null ){
			if( dResult[0].key == "osinfo.platform" ){		
				oVersionInfo.iSysVersion = oVersionInfo.iSysVersion + " for " + dResult[0].value;

			}else{
				alert("Error requesting stat on osinfo!");		
				mSetWrapper( numConstWrapperStateConnect );
			}
		}else{
				alert("Error requesting stat on osinfo!");						
				mSetWrapper( numConstWrapperStateConnect );
		}
	}
			
	
	mConfig_RequestNewTree();
	//mSetWrapper( numConstWrapperStateMain );

}

// ==============================
//  Handling config data
// ==============================
function mConfig_RequestNewTree(){
	// go to waiting state display
	mSetWrapper( numConstWrapperStateWaiting );
	// alert("before" );
	mEmiRpcSend( "emi.conf.get", {"key":"*","rec":true,"state":"new"} , "mDoConfig_RequestNewTreeComplete");
}

function mDoConfig_RequestNewTreeComplete( dResult ){
	if( dResult == null ){
		 // alert("Config timeout");
		// do nothing, its a non-critical error
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		if( dResult.result != null ){
			mOldKeysFromResult(dResult.result);
			mInitNewKeys();
		}else{
			// do nothing here
		}
	}
	
	// here we also need to get the diff for the old tree
	mEmiRpcSend( "emi.conf.diff", null , "mDoConfig_RequestDiffTreeComplete");
}

function mDoConfig_RequestDiffTreeComplete( dResult ){
	if( dResult == null ){
		alert("Diff timeout");
		mSetWrapper( numConstWrapperStateMain );
		return;
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		if( dResult.result != null ){
			// in this particular case old keys will hold only diff
			mOldKeysFromResult(dResult.result);
		}else{
			// do nothing here
		}
	}
	// at this point of time we need to go back to configscreen
	mSendStat("hostname.hostname", "mConfig_RequestHostnameComplete");
}


// REQUESTING THE Host name info 
function mConfig_RequestHostnameComplete(dResult){
//vRpcId = 99;
	//alert("response"+mSimpleJSONStringify(dResult));
	if( dResult == null ){
		// do nothing, its a non-critical error
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
	
		if( dResult[0] != null ){
			if( dResult[0].key == txtHostnameKey ){		
				oVersionInfo.iHost = dResult[0].value;

			}else{
				alert("Didnt receive a correct hostname for request!");
					mSetWrapper( numConstWrapperStateMain );

			}
		}else{
				alert("Didnt receive a correct RESULT for hostname request!");		
				mSetWrapper( numConstWrapperStateMain );
		}
	}

	// getting the system varsion info
	mEmiRpcSend( "emi.conf.get", {"key":"*","rec":true,"state":"old"} , "mConfig_RequestOldDataComplete");
}

function mConfig_RequestOldDataComplete(dResult){
	if( dResult == null ){
		alert("Old Tree Request timeout");
		mSetWrapper( numConstWrapperStateMain );
		return;
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		if( dResult.result != null ){
			// in this particular case old keys will hold only diff
			mRealOldKeysFromResult(dResult.result);
		}else{
			// do nothing here
		}
	}
	// at this point of time we need to go back to configscreen
	mSetWrapper( numConstWrapperStateMain );
}

// ==============================
//  EMI-RPC handling.
// ==============================
// It turns out that we have a multi-threaded execution here
// the call back and the main script will be executed cuncurrently!
// that does create an issue, we need to serialize the requests.
// This also presents an opportunity to handle the timeouts

var vRpcTimeout = 10000;

// vRpcId is incremented by one after each send
var vRpcId = 1;

// SessionID for the EMI-RPC
var vRpcSession = "";

// variable for the RPC serialization
var vRpcCallback = true;
var vRpcCallTO;
//var oRpcData;
var vSavedCallback;

// saving the data for retry
var vSaveParamMethod;
var vSaveParamParams;
var vSaveParamCallback;
var vBusyRpcId = -1;
var vBusyRpcCount = 0;

// mEmiRpcSends a request and returns resulting data or null
function mEmiRpcSend(vMethod, vParams, vCallback){
	// constructing the data
	var vObj = { "EMI-RPC":"1.0", "id":1, "method":""};
	
	if( vParams != null ){
	
		if( vRpcSession!="" ){
			vParams['session'] = vRpcSession;			
		}
		vObj['params']=vParams;
		
	}
	
	vObj['id']=vRpcId;
	vRpcId = vRpcId + 1;
	vObj['method']=vMethod;
	
	// sending JSON request
	// vRpcCallback = false;
	vSavedCallback = vCallback;

vSaveParamMethod = vMethod;
vSaveParamParams = vParams;
vSaveParamCallback = vCallback;
	vBusyRpcId = vRpcId;
	
	mSendJSONP( "mEmiRpcCallback" ,mSimpleJSONStringify(vObj) );
	
	// now waiting for vRpcCallBack to become true or TIMEOUT 10 seconds

	// Here we set a timeout event to wake us up
	// if the response will never come or will be
	// incorrect
	mEmiRpcTimeout( vCallback+"(null)", vRpcTimeout );
}

// EMI-RPC Error Reporting
// very simple reporting right now
function mEmiRpcSayError(dError){
	alert( "Error:" + dError.code + "("+ dError.message+ ")");
}

// mEmiRpcCallback will be called every time,t here is anything to process.
// the reall callback is saved in vSavedCallback. 
function mEmiRpcCallback( dResult ){
 	if( dResult == null ){
 		eval(vSavedCallback+"(null)" );
 	}
 	
	var vProcessing = eval ( dResult );
	
	if( vProcessing.id !=  vRpcId - 1){
		// we do nothing here,
		// probably its just a oob packet
		return;
	}
	
	// else we have the expected id, now its time to check the result
	// vRpcCallback = true;  // cancel timeout
	clearTimeout(vRpcCallTO);
	
	// Handling the system busy thing in here
	if( dResult.error != null ){ // error
		if( dResult.error.code == 700 ){ // busy 
			//alert("sys busy" + vBusyRpcCount);
			if( vBusyRpcId == (vRpcId - 1)){ // last id is -1 - same strain
			//alert("old strain" );
				if( vBusyRpcCount == 5){ // limit is reached
					// will continue to the callback with the error
				}else{
					vBusyRpcCount++;
					setTimeout("mSysBusyTimeout()", 1000);
					return;
				} // limit
			}else{ // new strain
			//alert("new strain" );
				vBusyRpcCount = 2;
				setTimeout("mSysBusyTimeout()", 1000);
				return;
			} // strain
		} // busy
	} // error
	
	eval( vSavedCallback+"(vProcessing)" );
	
}

function mSysBusyTimeout(){
			//alert("trying to send" );
	eval('mEmiRpcSend(vSaveParamMethod, vSaveParamParams , vSaveParamCallback)');
}


// this method waits till the TO comes to 0
function mEmiRpcTimeout(dCallback, dRemaining){
	var vInterval = 500;

	//if( !vRpcCallback ){
		if( dRemaining == 0 ){
			eval( dCallback );
	
		} else {
	
			dRemaining = dRemaining - vInterval;
			if( dRemaining < 0 ){
				dRemaining = 0;
			}
			vRpcCallTO=setTimeout('mEmiRpcTimeout("'+dCallback+'",'+ dRemaining +')', vInterval);
		}
	//} 
}


// ================================================================================== 
// mSendJSONP method assembles and sends given parameters with given callback param
// ==================================================================================

function mSendJSONP( dCallback, dRequest ){
	//alert("sent jsonp");
	//vdebug
//alert("Request:" + mSimpleJSONStringify(dRequest));
    var dd = new Date();
//	alert((vRequest));
	var ff;
	// checking the iAddress for the proper 
	if( oConnect.iAddress != null ){
		if(oConnect.iAddress.substring(0,7) != "http://"){
			//alert("missing http");
			ff = "http://" + oConnect.iAddress;
		}else{
			ff = oConnect.iAddress;
		}
		if( oConnect.iAddress.indexOf(':',7) == -1 ){
			//alert("missing port");
			ff = ff+":2001";
		}		
		
	}
	
	var aa = ff+"/emid";
	var bb = DebugUrl();
	if( bb != null){
		aa = bb;
	}
    var url = aa+"?callback="+dCallback+"&date="+dd.getTime()+"&request="+encodeURIComponent(dRequest);
	
	//dbAlert( url );	
    
    var script = document.createElement("script");        
    script.setAttribute("src",url);
    script.setAttribute("type","text/javascript");                
    document.body.appendChild(script);
}


// ============================== 
// || Main Navigation Handling ||
// ==============================

// mNavMouseOver activates when mouse over a single item in the list
// here we activate the visual for 1 item and deactivate for the others
//      ( just in case )
var gNavCurrent = "iLiConf";

function mNavMouseOver( dItem ){
	// dbAlert( "mNavMouseOver " + dItem );
	if( gNavCurrent != dItem ){
		document.getElementById(dItem).className = "hover";
	}
}

// mNavMouseOut activates when mouse exits the item.
// here we deactivate the visual for the element is something
function mNavMouseOut( dItem ){
	// dbAlert( "mNavMouseOut " + dItem );	
	if( gNavCurrent != dItem ){
		document.getElementById(dItem).className = "";
	}
}


function mNavMouseClick( dItem ){
	// dbAlert( "mNavMouseOut " + dItem );	
	if( gNavCurrent != dItem ){
		document.getElementById(gNavCurrent).className = "";
		document.getElementById(dItem).className = "current";
		gNavCurrent = dItem;
		mSetContainer( dItem );
	}
}

// ===================
//	Working with subnav
// ===================
// mSubNavMouseClick activates when mouse click on the span.
var gSubNavCurrent = "";

function mSubNavMouseClick( dItem ){
	// dbAlert( "mNavMouseOut " + dItem );	
	if( gSubNavCurrent != dItem ){
		document.getElementById(gSubNavCurrent).className = "";
		document.getElementById(dItem).className = "current";
		gSubNavCurrent = dItem;
		// setting the appropriate variable
		mSaveSubnavs();
		
		if( gSubNavCurrent == "iConfigReview"){
			mConfigurationRefresh();
		}
		//TODO Action here
	}
}

// stat flag
var gDoStatOnce = 0;
// adjusting subnav to look proper
function mAdjustSubnavs(){
	if( vCurrentContainer == txtContainerStateConfig ){
		document.getElementById("iConfigEdit").className = "";
		document.getElementById("iConfigReview").className = "";
		gSubNavCurrent = objTxtConfiguration.iTabCurrent;
		mSaveSubnavs();		
	}
	else if( vCurrentContainer == txtContainerStateStat ){
		gSubNavCurrent = "";			
		// do nothing?
		if(gDoStatOnce == 0 || vOldStatData == "") {
			mRefreshStat();
			gDoStatOnce = 1;
		}else{
			document.getElementById("data").innerHTML = vOldStatData;
		}
	}
	else if( vCurrentContainer == txtContainerStateSys ){
		gSubNavCurrent = "";			
	}
	else if( vCurrentContainer == txtContainerStateUtil ){
		gSubNavCurrent = "";			
	}
	else if( vCurrentContainer == txtContainerStateHelp ){
		gSubNavCurrent = "";			
	}
	else if( vCurrentContainer == txtContainerStateBug ){
		gSubNavCurrent = "";			
	}
	else{
		dbAlert( "mAdjustSubnavs : BAD STATE" + vCurrentContainer );			
	}
	
	if( document.getElementById(gSubNavCurrent) ){
		document.getElementById(gSubNavCurrent).className = "current";
	}
}

function mSaveSubnavs(){
	if( vCurrentContainer == txtContainerStateConfig ){
		objTxtConfiguration.iTabCurrent = gSubNavCurrent;
		document.getElementById("iConfigReview").title="Review Changes (" + mCalcKeys(objOldKeys) + ")";
		document.getElementById("iReviewChangesS").innerHTML="Review Changes (" + mCalcKeys(objOldKeys) + ")";
		
		if( gSubNavCurrent == "iConfigEdit"){
			document.getElementById("content").innerHTML = objTxtConfiguration.iContent;
			document.getElementById("actions").innerHTML=objTxtConfiguration.iActions;
			document.getElementById("id_save_changes").value="Save Changes";
			document.getElementById("data").readOnly=false;
			}
		else{
			document.getElementById("content").innerHTML = objTxtReviewConfiguration.iContent;
			document.getElementById("actions").innerHTML=objTxtConfiguration.iReviewActions;
			//document.getElementById("data").readOnly=true;
			document.getElementById("id_save_changes").value="Discard Changes";
			};
		if( gSubNavCurrent == "iConfigEdit" ){
			document.getElementById("title").innerHTML = objTxtConfiguration.iTitleEdit;
			document.getElementById("data").value = mCreateRawText(objNewKeys);
		}else if (gSubNavCurrent == "iConfigReview"){
			document.getElementById("title").innerHTML = objTxtConfiguration.iTitleReview;
			//document.getElementById("data").value = mCreateRawText(objOldKeys);		
			document.getElementById("confold").innerHTML = "<h2>Current Configuration</h2><hr>"+mCreateHTMLText(objRealOldKeys);
			document.getElementById("confnew").innerHTML = "<h2>Changes</h2><hr>"+mCreateColoredHTMLText(mComposeReviewObject(), objColCode);
			//alert(document.getElementById("confnew/").innerHTML);
		}else{
			document.getElementById("title").innerHTML = "<h2>ERROR!</h2>";
			document.getElementById("data").value = "UI Internal Error";
		}
		
	}
	else if( vCurrentContainer == txtContainerStateStat ){

	}
	else if( vCurrentContainer == txtContainerStateSys ){
			
	}
	else if( vCurrentContainer == txtContainerStateUtil ){
		
	}
	else if( vCurrentContainer == txtContainerStateHelp ){
		
	}
	else{
		dbAlert( "mAdjustSubnavs : BAD STATE" + vCurrentContainer );			
	}
}



// on set configuration we have to
// 1. parse the window
// 2. send the changes with conf.set
// 3. remove the missing keys with conf.del
// 4. refresh the data
var oActionScript;
var oActionsLeft;
var oActionSavedCallback;
function mConfigurationSet(){
	//alert("Submit is pressed");
	
	
	// alert("data is parsed");
	// TODO fast fix for a bug, need to be done better
	if(	gSubNavCurrent == "iConfigEdit" ) {
		var objChangedKeys = mParseDataText( document.getElementById("data").value );
		oActionScript = mConvertToAction( objNewKeys, objChangedKeys);
		}else{
		//oActionScript = mConvertToAction( objNewKeys, objNewKeys);		
		// oActionScript = mConvertToActionNoDelete( objNewKeys, objOldKeys);		
		mRevertChanges();
		return;
		}
	//alert(oActionScript.length);
	//sending the commands one by one
	
	oActionsLeft = oActionScript.length;
	oActionSavedCallback = "mConfig_RequestNewTree()";
	if( gSubNavCurrent == "iConfigEdit" ){
		//alert("changing");
		objTxtConfiguration.iTabCurrent = "iConfigReview";	
	}

	
	mSetWrapper( numConstWrapperStateWaiting ); 
	mSendNextSetDel(); 
}

function mConfigurationRefresh(){
	mSetWrapper( numConstWrapperStateWaiting ); 
	mConfig_RequestNewTree();
	}

function mRevertChanges(){
	mSetWrapper( numConstWrapperStateWaiting ); 
	mEmiRpcSend( "emi.conf.revert", null , "mConfig_Revert_Complete");	
}

function mConfig_Revert_Complete(dResult){
	vRpcTimeout = 10000;
	if( dResult == null ){
		alert("Revert timeout");
		// do nothing, its a non-critical error
	}else{
		//clearTimeout(vRpcCallTO);
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		// we dont care about the result in here
	}
	objTxtConfiguration.iTabCurrent = "iConfigEdit" ;
	mConfig_RequestNewTree();
}

// ==========================
//  Actions for configuration
// ==========================
// on set configuration we have to
// 1. parse the window
// 2. send the changes with conf.set
// 3. remove the missing keys with conf.del
// 4. commit the data with clear=true flag
// 5. refresh the data
function mConfigurationApply(){
	//alert("Apply is pressed");
	var objChangedKeys;
	
	if(gSubNavCurrent != "iConfigEdit"){
		//document.getElementById("data").value = mCreateRawText(objNewKeys);
		}else{
		objChangedKeys = mParseDataText( document.getElementById("data").value );			
		}
		
	
	// alert("data is parsed");
	// TODO fast fix for a bug, need to be done better
	if(	gSubNavCurrent == "iConfigEdit" ) {
		oActionScript = mConvertToAction( objNewKeys, objChangedKeys);
		}else{
		oActionScript = mConvertToAction( objNewKeys, objNewKeys);		
		}
	//alert("AScript "+oActionScript.length);
	//sending the commands one by one
	
	oActionsLeft = oActionScript.length;
	oActionSavedCallback = "mConfig_Commit()";
	//alert( oActionScript.length );
	mSetWrapper( numConstWrapperStateWaiting ); 
	mSendNextSetDel(); 
}


function mSendNextSetDel( ){
	
	if( oActionsLeft > 0 ){
		var vCommand;
		var vParams = new Object();
		if( oActionScript [ oActionScript.length - oActionsLeft ].iCommand == "set" ){
			vCommand = "emi.conf.set";
			vParams["key"]= oActionScript [ oActionScript.length - oActionsLeft ].iKey;
			vParams["value"]= oActionScript [ oActionScript.length - oActionsLeft ].iData;
		}else 
			if( oActionScript [ oActionScript.length - oActionsLeft ].iCommand == "del" ){
			vCommand = "emi.conf.del";
			vParams["key"]= oActionScript [ oActionScript.length - oActionsLeft ].iKey;
		}else{
			alert("Error: bad command for action script!");
		}
		oActionsLeft --;
		mEmiRpcSend( vCommand, vParams , "mDoSetDel_Complete");
		
	}else{
		// do nothing
		eval( oActionSavedCallback );		
	}
}

function mDoSetDel_Complete( dResult ){
	if( dResult == null ){
		// alert("SetDel timeout");
		alert("Set or Delete operation timeout!");
		mSetWrapper( numConstWrapperStateMain );
		return;
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain ); 
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		// we dont care about the result in here
	}

	if( oActionsLeft == 0 ){
		oActionScript=new Array();

		// at this point we activate the saved callback
		eval( oActionSavedCallback );		
	}else{
		mSendNextSetDel( );
	}
}


// ====================
//  Committing the state: we need to set the timer to 30 seconds
// ====================
function mConfig_Commit(){
	vRpcTimeout = 30000;
	var vParams = new Object();
	vParams["clear"]=true;
	//vParams["test"]=true;
	mEmiRpcSend( "emi.conf.commit", vParams , "mConfig_Commit_Complete");	
}

function mConfig_Commit_Complete(  dResult ){
	vRpcTimeout = 10000;
	if( dResult == null ){
		alert("Commit timeout");
		// do nothing, its a non-critical error
	}else{
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
				mSetWrapper( numConstWrapperStateMain );
				return;
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		// we dont care about the result in here
	}
	objTxtConfiguration.iTabCurrent = "iConfigEdit" ;
	mConfig_RequestNewTree();
}


// =================== 
// || Waiting State ||
// ===================


// ===========
// || Debug ||
// ===========
var gDebug = false;
//var gDebugAddress = "127.0.0.1"; 
var gDebugAddress = "192.168.0.199"; 

function DebugUrl(){
	if(!gDebug){
		return;
	}
	
	if(/*vRpcId == 2*/0){
		//return "http://"+gDebugAddress+"/emid/test_session_start.php";
	}
/*	else if(vRpcId == 3){
		return "http://"+gDebugAddress+"/emid/test_conf_get_hostname.php";
	}*/
	else if(vRpcId == 100){
		return "http://"+gDebugAddress+"/emid/test_sys_version.php";
	}
	else if(vRpcId == 5){
		return "http://"+gDebugAddress+"/emid/test_conf_getnew.php";
	}
	else if(vRpcId == 6){
		return "http://"+gDebugAddress+"/emid/test_conf_getdiff.php";
	}/*
	else if(vRpcId == 7){
		return "http://"+gDebugAddress+"/emid/test_ok.php";
	}
	else if(vRpcId == 8){
		return "http://"+gDebugAddress+"/emid/test_ok2.php";
		//return "http://"+gDebugAddress+"/emid/test_conf_commit.php";
	}
	else if(vRpcId == 9){
		return "http://"+gDebugAddress+"/emid/test_conf_getnew2.php";
	}
	else if(vRpcId == 10){
		return "http://"+gDebugAddress+"/emid/test_conf_getdiff2.php";
	}*/
	/*else if(vRpcId == 7){
		return "http://"+gDebugAddress+"/emid/test_stat_gettask.php";
	}
	else if(vRpcId == 8){
		return "http://"+gDebugAddress+"/emid/test_stat_getprov.php";
	}
	else if(vRpcId == 9){
		return "http://"+gDebugAddress+"/emid/test_stat_getdata.php";
	}*/
	else{
		return oConnect.iAddress;
	}
}

function mConfigurationSave(){
	mSetWrapper( numConstWrapperStateWaiting );
	mEmiRpcSend( "emi.conf.save", null , "mConfSave_Complete");
}

function mConfSave_Complete(dResult){
	if( dResult == null ){
		alert("Save Configuration timeout");
		// do nothing, its a non-critical error
	}else{
		//clearTimeout(vRpcCallTO);
		if( dResult.error != null ){
			if( dResult.error.code != 0 ){ // real error
				mEmiRpcSayError( dResult.error );
			} else {
				// TODO: could be a warning or something. Not handling now.
			}
		}
		
		// we dont care about the result in here
	}

	mSetWrapper( numConstWrapperStateMain );
	return;
}

function dbAlert( dText ){
	if( gDebug ){
		alert ( dText );
	}
}
