/*
	Brief API Description
	
	Summary: This library is responsible for accessing and finding service speciffic errors/messages
	
	Background: 
	All errors/messages are predefined and stored in XML files that maintain structure that isolates error codes by category (that should be unique)
	Some SOAP speciffic errors/messages are stored in shared area (i.e. /shared/actionMessages/xml), other page/form speciffic messages can be localized to site
	
	Namespace: bam.actionMessages
	Property(s): > DefaultCategory - this is the category to be used if ommited in GetMessage method
	Method(s):	 > GetMessage(code, [category]) or GetMessage(status, [category])
					> code - string or numeric value that matches message code
					> status - object returned from SOAP services
					Ex: status: {code:"-3000",
						  detailList:[
							{messageKey:"address.line1", message:"duplicate group name"},
							{messageKey:"address.line2", message:"duplicate group name"}
						  ],
						  message:"Duplicate"
						}
					> category - this is service speciffic category name (codes will be looked up only within this category)
					  If ommited DefaultCategory value will be used
					
					Returns: {
						code: null, //Error/Message code
						details: [], //List of matched details
						messages: [], //All messages
						toString: function([delimeter]) //This delimeter separates multiple messages (default: "\n")
					}
				> LoadMessages(jsonpath1 [, jsonpath2, ...]) - This method loads errors/messages to be available for lookup
				!!! Use this method prior GetMessage call !!!
				Currently there is an XML to JSON converter that takes xml query string parameter to produce JSON output
				Ex:  /shared/actionMessages/getjson.jsp?xml=/shared/actionMessages/xml/registration.xml - will load "/shared/actionMessages/xml/registration.xml"
	
	Usage Example:
		var _am = bam.actionMessages; //Alias
		_am.LoadMessages(
			"/shared/actionMessages/getjson.jsp?xml=/tests/xml/errors.xml",
			"/shared/actionMessages/getjson.jsp?xml=/shared/actionMessages/xml/registration.xml"
		);
		var msg = _am.GetMessage({code:"-3000",
			detailList:[{messageKey:"address.line1", message:"duplicate group name"},{messageKey:"address.line2", message:"duplicate group name"}],
			message:"Duplicate"
		}, "registration");
		alert(msg.toString());			  
*/
bam.extend({
	actionMessages: (function() {		
		var _errors = {};
		//get speciffic detail
		var _findDetailByKey  = function(dl, key) {
			var _out = null;
			if((typeof(dl) === "object" || typeof(dl) === "array") && typeof(key) ==="string") {
				var _e = dl.length-1, _c = null;
				do {_c = dl[_e];if(!!_c && _c.key===key){_out=_c;break;}}while(_e--);		
			}
			return _out;
		};
		//Gets reference to error category
		var _getCategory = function(category) {
			var _cat = category || _self.DefaultCategory;
			return _errors[_cat] || null;
		};
		//Finds and returns raw message		
		var _getMessage = function(code, category) {
			var _out = null;
			var _cat = _getCategory(category);
			if(!!_cat) {				
				var _code = String(code) || "0";
				var _e =_cat.length-1, _c = null;
				do {_c =_cat[_e];if(!!_c && _c.code===_code){_out=_c;break;}}while(_e--);
			}
			return _out;
		};
		//Message object output template
		
		var _message = (function() {
			var _msg = {
				code: null,
				details: [],
				messages: [],
				isError: false,
				activate: function(mNode, details) {
					_msg.details = [];
					_msg.code = mNode.code;
					_msg.messages = [];
					_msg.isError = mNode.isError || false;
					if(!!details && !!mNode.details) {
						var _d = details.length - 1,
						_c = null, //Current detail from status						
						_f = null; //Found detail from message
						if(_d >= 0) {
							do {
								_c = details[_d];
								if(!!_c) {
									_f = _findDetailByKey(mNode.details, _c.messageKey);
									if(!!_f) { _msg.messages.push(_f.message); _msg.details.push({key:_f.key,message:_f.message}); }
								}
							} while(_d--);
							if(_msg.messages.length === 0) {
								//If no details found - return parent message
								_msg.messages.push(mNode.message);
							}
						}
					} else {
						//If no details - return parent message
						_msg.messages.push(mNode.message);
					}					
				},
				toString: function(delimeter) {
					var _delim = delimeter || "\n";
					return _msg.messages.join(_delim);
				},
				wrap: function(tag) {
					var _out = [];
					if(typeof(tag) === "string") {
						$.each(_msg.messages, function() {
							_out.push("<"+tag+">"+this+"</"+tag+">");
						});
					}
					return _out.join("");
				}
			};
			return _msg;
		})();		
		//Fatory method for creating Message object from raw exception object
		var _createMessage = function(mNode, details) {			
			var _out = null;
			if(!!mNode) { 
				_out = bam.clone(_message);
				_out.activate(mNode, (!!details && details.reverse()));
				_out.activate = null; //Override method to make it inaccessible	
				//DO NOT USE delete - it'll reset activate to original functionality
			}
			return _out;
		};
		//Error finders
		var _self = {
			DefaultCategory:"default",
			GetMessage: function(status, category) {
				var _out = null;
				var _msg = null;
				if(typeof(status)==="object" && status.code) {
					_msg = _getMessage(status.code, category);
					_out = _createMessage(_msg, (status.detailList || null));
				} else {
					_msg = _getMessage(status, category);
					_out = _createMessage(_msg, null);
				}
				return _out;
			},
			LoadMessages: function() {
				function _syncLoad(path) {
					$.ajax({
						type: "GET",
						url: path,
						dataType: "json",
						async:false,
						success: function(json) {
							bam.extend(_errors, json);							
						}
					});
				}
				if(arguments.length > 1) {
					var aLen = arguments.length-1;
					do {
						_syncLoad(arguments[aLen]);
					} while(aLen--);
				} else {
					_syncLoad(arguments[0]);
				}
			}
		};	
		return _self;		
	})()
});