/**
 * 
 * @author ganesh.rajasekaran@ignistech.com
 */

/**
 * Utility class to form the parameter as json format.<b>
 * 
 * <B>Note:<B> This is a protected class.
 * 
 * @author ganesh.rajasekaran
 */

Tp.core.RequestParamAssembler = function() {
	// this.parameters = new Hash();
	this.paramArray = [];

	/**
	 * 
	 */
	this.assembleListAsParam = function(objectList, parentPropertyName) {

		if (objectList == null || objectList.length == 0) {
			return;
		}

		this.assembleString(parentPropertyName + ".count", objectList.length);
		for ( var j = 0; j < objectList.length; j++) {

			var element = objectList[j];
			
			for ( var i in element) {
				
				this.assembleString(parentPropertyName + "[" + j + "]." + i,
						element[i]);

			}
		}

	};

	/**
	 * Assemble parameter for Data Objects.
	 */
	this.assembleObject = function(object, parent) {

		if (object == null) {
			return;
		}

		for ( var i in object) {
			var msg = i + "\n" + object[i];

			// If this property (i) is an object, then recursively process the
			// object
			if (typeof object[i] == "object") {

				if (parent != null) {
					this.assembleObject(object[i], parent + "." + i);
				} else {
					this.assembleObject(object[i], i);
				}

			} else {

				if (parent != null) {
					this.assembleString(parent + "." + i, object[i]);
				} else {
					this.assembleString(i, object[i]);
				}
			}
		}
	}

	/**
	 * Assemble parameter for plain string.
	 */
	this.assembleString = function(paramName, value) {
		// this.parameters.set(paramName, value);
		if(value == '<br>' || value == '<br/>'){
			value = '';
		}
		this.paramArray.push( {
			param :paramName,
			paramValue :value
		});
	}

	/**
	 * Form the properitry custom request parameter.
	 */
	this.getRequestParameters = function() {
		return this.parameters;
	},

	this.getRequestParamsAsObj = function() {
		var paramObj = "";
		var val = "";
		for ( var i = 0; i < this.paramArray.length; i++) {
			// paramObj = paramObj.replace("\"", "\\\"");

			val = this.paramArray[i].paramValue + "";
			 if(val.toLowerCase().indexOf("<ol>" ) == 0 
						|| val.toLowerCase().indexOf("<ul>") == 0){
				 val = escape(val); 
			 }
			 else{
				 val = val.replace(new RegExp("\"", "g"), "\\\"");
				 val = val.replace(new RegExp("\'", "g"), "\\\'");
				// val = val.replace(new RegExp("\\\n", "g"), "\\\\n");
				 val = val.replace(new RegExp("(\\\r\\\n|\\\n)", "g"), "\\\\n");
			 }
			 val = val.replace(new RegExp("(\\\r\\\n|\\\n)", "g"), "\\\\n");
			paramObj = paramObj + "'" + this.paramArray[i].param + "':'" + val
					+ "',";
		}
		paramObj = paramObj + "'client':'tp-core'";

		paramObj = "({" + paramObj + "})";
		
		var obj = eval('(' + paramObj + ')');
		return obj;
	}
}

/**
 * Async Response Handler class. <BR>
 * This handler class provides set of utility method to handle response from the
 * server. Most of the time the the response will be JSON format & also well
 * defined json object.
 * 
 * <B>Note:<B> This is a protected class.
 * 
 * @author ganesh.rajasekaran
 */
Tp.core.JsonResponseHandler = {

	/**
	 * Get the array of objects from the jsonString passed in.
	 * 
	 * @param jsonString
	 *            string raw response from server
	 * @return Array array of objects.
	 */
	getData : function(jsonString) {
		if (jsonString == null || jsonString.length <= 0) {
			return [];
		}
		
		jsonString = jsonString.replace(new RegExp("\\\\n", "g"), "n");
		var jsonObject = eval('(' + jsonString + ')');
		var data = null;

		/*
		 * According to our logic, the server sends the response as array and
		 * name of array property is "data".
		 */
		if (jsonObject) {
			data = jsonObject;
		}
		return data;
	},

	/**
	 * Dissemble the Json String to get the simple String.
	 * 
	 * @param jsonString
	 *            string raw response from server
	 * @return String
	 */
	dissembleObject : function(jsonString) {
		var data = this.getData(jsonString);
		return data;
	}
}

/**
 * A <B>Proxy</B> to all the Service classes of js layer.<b> Basically, it
 * hides the complexity of the communication between the server & client. As of
 * now, we are using the Prototype Ajax object to send & receive message from
 * the server.
 * 
 * @author ganesh.rajasekaran
 */

/**
 * The default constructor which takes the configuration as input. The structure
 * of the config object as follows,
 * 
 * var config = { <BR>
 * context : // Context object passed by the Client, <BR>
 * url : // URI to send the request <BR>
 * parameters: // parameter to be sent to the server. <BR>
 * onResponseSuccess: <BR>
 * onResponseFailed: }
 * 
 * @param pConfig
 *            configuration object.
 */
Tp.core.ServiceProxy = function(pConfig) {
	this.config = pConfig;
	this.type = pConfig.type;
	this.url = pConfig.url;
	this.parameters = pConfig.parameters;

	/**
	 * <B>Reponsibilities</B> - Send the message as HTTP request to the Server. -
	 * Receive the response from the server. - Handle the sync communication. -
	 * (or) Handle the Async communication.
	 */
	this.send = function() {
		// TODO : check for this condition.. ?

		var url = this.url;
		var configLocal = this.config;

		var sync = false;
		var output = null;

		Ext.Ajax.request( {
			url :url,
			params :this.parameters,
			timeout :900000,
			success : function(result) {
				configLocal.onResponseSuccess(result.responseText,
						configLocal.context);
			},
			failure : function(result) {
				configLocal.onResponseFailed(configLocal);
			},
			method :'POST',
			asynchronous :true
		});

		/*
		 * How simple to make a request, technology is so fast man. :) :)
		 * 
		 * new Ajax.Request(url, { parameters :this.parameters, onSuccess :
		 * function(result) { // alert("Server result : " +
		 * result.responseText);
		 * configLocal.onResponseSuccess(result.responseText,
		 * configLocal.context); }, onFailure : function(result) { //
		 * alert("Request Failed..... " + result.responseText);
		 * configLocal.onResponseFailed(configLocal); }, method :'POST',
		 * asynchronous :true });
		 */
	}
};

/**
 * The default constructor which takes the configuration as input. The structure
 * of the config object as follows,
 * 
 * var config = { <BR>
 * 
 * context : // Context object passed by the Client, <BR>
 * actionId : // command action id to be executed by the server <BR>
 * parameters: // command parameter to be sent to the server. <BR>
 * onSuccess: <BR>
 * onBusinessFailure: <BR>
 * onError : <BR> }
 * 
 * @param pConfig
 *            configuration object.
 */
Tp.core.TalentPortalServer = function(pConfig) {
	this.config = pConfig;
	this.url = "TalentPortalService?ACTION_ID=";

	/**
	 * <B>Reponsibilities</B> - Send the message as HTTP request to the Server. -
	 * Receive the response from the server. - Handle the sync communication. -
	 * (or) Handle the Async communication.
	 */
	this.request = function() {

		var localObject = this;

		var localConfig = this.config;

		var requestConfig = {
			context :this.config,
			url :this.url + this.config.actionId,
			parameters :this.config.parameters.getRequestParamsAsObj(),
			onResponseSuccess : function(result, configLocal) {
				actionResult = Tp.core.JsonResponseHandler
						.dissembleObject(result);
				localObject.onSuccess(actionResult, localConfig);
			},
			onResponseFailed : function(configLocal) {
				localObject.onFailure();
			}
		};
		new Tp.core.ServiceProxy(requestConfig).send();

	};

	/**
	 * 
	 */
	this.onSuccess = function(ationResult, localConfig) {
		var resultStatus = ationResult.actionResultStatus;
		if (resultStatus == "F_ERROR") {

			if (ationResult.result[0]
					&& ationResult.result[0].key == "USER_NOT_LOGGED_ID") {
				alert("User Session Expired");
				window.location.href = "index.jsp";
			}

			localConfig.onBusinessFailure(ationResult.result);
		}

		if (resultStatus == "ERROR" || resultStatus == "T_ERROR") {

			if(localConfig.onError){
				localConfig.onError(ationResult.result);
			}
		}

		if (resultStatus == "SUCCESS") {

			formattedResult = ationResult["result"];

			localConfig.onSuccess(formattedResult);
		}
	};

	this.packAsList = function(result) {

		return formattedResult;
	};

	/**
	 * 
	 */
	this.onFailure = function() {
		if (this.config.onError) {
			this.config.onError(null);
		}
	}
}

/**
 * @param pConfig = {
 *            <BR>
 *            formObject : // form Object ,<BR>
 *            formGridFieldConfig : //array of property - form fields mapping
 *            <BR> }
 */
Tp.core.FormGridDataStateManager = function(pConfig) {

	this.config = pConfig;
	this.formObject = pConfig.formObject;

	this.createNewDataObject = function(pkProperty, recordId) {

		var rawJSON = "{";

		var totalPropConfig = this.config.formGridFieldConfig.length;
		for ( var j = 0; j < totalPropConfig; j++) {

			var formGridFieldConfig = this.config.formGridFieldConfig[j];

			var propValue = this.getFormValue(formGridFieldConfig);
			/*propValue = propValue.replace(new RegExp("\"", "g"), "\\\"");
			propValue = propValue.replace(new RegExp("\'", "g"), "\\\'");
			propValue = propValue.replace(new RegExp("\\\n", "g"), "\\\\n");*/
			rawJSON += formGridFieldConfig.property + ":'" + escape(propValue) + "',";

		}
		rawJSON += pkProperty + ": '" + recordId + "',";
		rawJSON += "status: 'NEW'";
		rawJSON += "}";
		var jsonObject = eval('(' + rawJSON + ')');
		return this.unescapeFormFields(jsonObject);
	};

	this.unescapeFormFields = function(row) {

		var totalPropConfig = this.config.formGridFieldConfig.length;
		for ( var j = 0; j < totalPropConfig; j++) {

			var formGridFieldConfig = this.config.formGridFieldConfig[j];
			var fieldValue = row[formGridFieldConfig.property];
			
			row[formGridFieldConfig.property] = unescape(fieldValue).replace(new RegExp("\\\\n", "g"), "n");
			
			/*row[formGridFieldConfig.property] = row[formGridFieldConfig.property]
					.replace(new RegExp("\\\\n", "g"), "n");*/

		}
		return row;
	}

	this.updateGridRow = function(gridRow) {

		var totalPropConfig = this.config.formGridFieldConfig.length;
		for ( var j = 0; j < totalPropConfig; j++) {

			var formGridFieldConfig = this.config.formGridFieldConfig[j];

			gridRow.set(formGridFieldConfig.property, this
					.getFormValue(formGridFieldConfig));
		}
	};

	this.mergeRow = function(destinationObj, sourceObj) {

		var totalPropConfig = this.config.formGridFieldConfig.length;
		for ( var j = 0; j < totalPropConfig; j++) {
			var formGridFieldConfig = this.config.formGridFieldConfig[j];
			var val = sourceObj[formGridFieldConfig.property];
			if(val == '<br>' || val == '<br/>'){
				val = '';
			}
			destinationObj[formGridFieldConfig.property] = val;
		}

	};

	this.updateFormFields = function(row) {

		var totalPropConfig = this.config.formGridFieldConfig.length;
		for ( var j = 0; j < totalPropConfig; j++) {

			var formGridFieldConfig = this.config.formGridFieldConfig[j];

			var propValue = row[formGridFieldConfig.property];

			if (formGridFieldConfig["type"] == "Date") {

				this.formObject.findField(formGridFieldConfig.formProperty)
						.setValue(propValue);
			} else if (formGridFieldConfig["type"] == "ComboText") {
				this.formObject.findField(formGridFieldConfig.formProperty)
						.setRawValue(propValue);
			} else {
				this.formObject.findField(formGridFieldConfig.formProperty)
						.setValue(propValue);
			}
		}

	}

	this.getFormValue = function(formGridFieldConfig) {

		var propValue = this.formObject.findField(
				formGridFieldConfig.formProperty).getValue();

		if (formGridFieldConfig["type"] == "Date") {

			propValue = this.formObject.findField(
					formGridFieldConfig.formProperty).getValue();
			propValue = Tp.core.DateUtil.parseUIDateToString(propValue);

		} else if (formGridFieldConfig["type"] == "ComboText") {
			propValue = this.formObject.findField(
					formGridFieldConfig.formProperty).getRawValue();

		}

		return propValue;
	}

}

/**
 * 
 */
Tp.core.GridDataStateManager = function(pConfig) {
	this.config = pConfig;
	this.primaryKey = pConfig.primaryKey;
	this.status = pConfig.status;
	this.data = pConfig.rows;

	this.addRow = function(row) {

		row[this.status] = "NEW";
		this.data.push(row);
	};

	this.deleteRow = function(row) {

		var rowObject = this.findRow(row);

		if (rowObject != null) {
			if (rowObject[this.status] == "NEW") {
				rowObject[this.status] = "VOID";
			}

			if (rowObject[this.status] == "EXISTING") {
				rowObject[this.status] = "DELETE";
			}
		}
	};

	this.markRowDiry = function(row) {

		var rowObject = this.findRow(row);

		if (rowObject != null) {

			if (rowObject[this.status] == "NEW") {
				rowObject[this.status] = "NEW";
			}

			if (rowObject[this.status] == "EXISTING") {
				rowObject[this.status] = "MODIFIED";
			}
		}
	};

	this.findRow = function(row) {

		var rowObject = null;

		for ( var i = 0; i < this.data.length; i++) {
			if (this.data[i][this.primaryKey] == row[this.primaryKey]) {
				rowObject = this.data[i];
			}
		}

		return rowObject;
	};

	this.getDataToBeSaved = function() {
		var rows = [];

		for ( var i = 0; i < this.data.length; i++) {
			/*if (this.data[i][this.status] == "NEW"
					|| this.data[i][this.status] == "DELETE"
					|| this.data[i][this.status] == "MODIFIED") {
					rows.push(this.data[i]);
			}*/
			
			rows.push(this.data[i]);
		}
		return rows;
	};

	this.debug = function(property) {

		for ( var i = 0; i < this.data.length; i++) {
			alert(this.data[i][property] + " : " + this.data[i][this.status]);
		}
	}
}

Tp.core.DateUtil = {

	parseUIDate : function(date) {
		var retValue = "";

		if (date != null) {

			retValue = date.getDate() + "/" + (date.getMonth() + 1) + "/"
					+ date.getFullYear();
		}

		return retValue;
	},

	parseMarshallingDate : function(date) {
		var retValue = "";

		if (date != null) {
			retValue = date.getDate() + "/" + (date.getMonth() + 1) + "/"
					+ date.getFullYear();
		}
		return retValue;
	},
	parseUIDateFormat : function(date) {
		var retValue = "";
		if (date != null) {

			var month = (date.getMonth() + 1);
			var day = date.getDate();

			if (date.getMonth() + 1 < 10) {
				month = "0" + (date.getMonth() + 1);
			}
			if (date.getDate() < 10) {
				day = "0" + date.getDate();
			}

			retValue =  day + "-" + month + "-" +date.getFullYear();
		}
		return retValue;
	},

	parseUIDateToString : function(date) {
		var retValue = "";

		if (date != null) {

			var month = (date.getMonth() + 1);
			var day = date.getDate();

			if (date.getMonth() + 1 < 10) {
				month = "0" + (date.getMonth() + 1);
			}
			if (date.getDate() < 10) {
				day = "0" + date.getDate();
			}

			retValue = date.getFullYear() + "-" + month + "-" + day;
		}
		return retValue;
	},

	parseMonthYearToString : function(date) {
		var retValue = "";

		if (date != null) {
			month = (date.getMonth());

			var displayMonth = Date.getShortMonthName(month);

			retValue = displayMonth + "," + date.getFullYear();
		}
		return retValue;
	},
	parseUIDateAndTimeToString : function(date, time) {
		var retValue = "";
		var month = "";
		var day = "";
		var hrmin = "";
		var min = "";
		if (date != null) {
			month = (date.getMonth() + 1);
			day = date.getDate();

			if (date.getMonth() + 1 < 10) {
				month = "0" + (date.getMonth() + 1);
			}
			if (date.getDate() < 10) {
				day = "0" + date.getDate();
			}
		}
		if (time != null) {
			hrmin = time;

		}
		retValue = date.getFullYear() + "-" + month + "-" + day + " " + hrmin;

		return retValue;

	}

}
