/* Client side JS delegate for the panel framework (see baseFields.cfc)
 * (#this.jss# is an instance of PanelController)
 */

/* Validated with http://jslint.com/ Edition 2009-10-04 */

/*jslint onevar: true, browser: true, evil: true, forin: true */
/*global Ext:false,DWREngine:false,clearUndisplayedFields:false, trim:false,
 base64Decode:false, applyEmbeddedCSS:false, applyEmbeddedJS:false,
 extractFormData:false*/

function PanelController(){}

Ext.apply(PanelController.prototype, {
  cssLoaded: false,
	submitted: false,
	submitbtn: null,

	/*
		config is called by the framework when the panel first
		comes up and on each round trip to the server.

		info is an array of field config objects pertaining to fields that
		was actually rendered when the display method was called.

		settings is the server side panel settings struct, in json format.
	*/
	config: function(info, settings)
	{
		var f,i,j,tryToFocus=false,that=this;

		this.fieldInfo=info;
		this.settings=settings;

		// create lookup of field dom elements, keyed by field name
		this.fields={};

		// create array of fields that have error
		this.errorFieldInfo=[];

		for (i=0,j=info.length;i<j;i++)
		{
			f=info[i];
			this.fields[f.fieldname]=document.getElementById(f.domid);
			if (f.haserror)
			{
				tryToFocus=true;
				this.errorFieldInfo.push(f);
			}
			if (f.focus)
			{
				tryToFocus=true;
			}
		}

		if (tryToFocus)
		{
			/* async focus on first field with error, or first user focus field */
			setTimeout(function(){that.doFieldFocus();},0);
		}
	},

	getField: function(fieldName)
	{
		return this.fields[fieldName];
	},

	/* attempt to set focus to the first field that has an error
				if that fails, try the next field, etc.
				if no fields have an error defined, set focus to first field
				that has focus=true that succeeds
	*/
	doFieldFocus: function()
	{
		var f,i,j;

		/*
			if one or more fields have an error, focus on the first
			field possible.
		*/
		if (this.errorFieldInfo.length)
		{
			for (i=0,j=this.errorFieldInfo.length;i<j;i++)
			{
				f=this.errorFieldInfo[i];
				try
				{
					this.fields[f.fieldname].focus();
					return;
				}
				catch (ex1)
				{
				}
			}
		}
		else
		{
			/*
				if not error, focus on first field
				that has focus set.  if that fails, try the next one, etc.
			*/
			for (i=0,j=this.fieldInfo.length;i<j;i++)
			{
				f=this.fieldInfo[i];
				if (f.focus)
				{
					try
					{
						this.fields[f.fieldname].focus();
						return;
					}
					catch (ex2)
					{
					}
				}
			}
		}
	},

	/*

		connect fields together via the enter key
		so that pressing enter on a field will advance the focus to the
		next field in the specified order similar to how tab normally does
		except that buttons that are found are connected to the onclick
		handler so that they can submit the panel by
		hitting enter from the previous field.

		fields is a list of field names and|or dom ids in the order that they should
		be threaded together.

	*/
	threadFields: function(fields)
	{
		var i,j,field,last;

		function threadToField(field)
		{
			if (field.getAttribute("type") === "button")
			{
				return function(e) {
					var c;
					e=e||event;
					c=e.keyCode||e.which;
					if (c===13)
					{
						/* route to button click */
						field.onclick(e);
						return false;
					}
				};
			}
			else
			{
				return function(e) {
					var c;
					e=e||event;
					c=e.keyCode||e.which;
					/* route to focus on next field */
					if (c===13)
					{
						field.focus();
						return false;
					}
				};
			}
		}

		if (fields && fields.length)
		{
			for (i=0,j=fields.length; i<j; i++)
			{
				field=this.getField(fields[i]);

				/* if field not found directly, look for it by id */
				if (!field)
				{
					field = document.getElementById(fields[i]);
				}

				if (field)
				{
					if (last)
					{
						last.onkeydown = threadToField(field);
					}
					last=field;
				}
			}
		}
	},

	load: function(parms)
	{
		var formData, n;
		if (this.settings.waitmsgactive)
		{
			this.showWaitMsg(this.loadingMessage);
		}

		formData = Ext.apply({},{cfc:this.cfc},this.request.parm);

		if (parms)
		{
			for (n in parms)
			{
				formData[n.toLowerCase()] = parms[n];
			}
		}
		if (!formData.action)
		{
			formData.action = "";
		}
		DWREngine._execute("/resources/ajax/ajaxPanels.cfc" +
			this.settings.noauditparm, null, "loadCfc", formData,
			this.loadResponse.createDelegate(this));
	},

	fnSubmit: function(action, button, waitMsg)
	{
		var parms, formData;
		if (typeof(action) == "object")
		{
			parms = action;
		}
		else
		{
			parms = {action:action, button:button, waitMsg:waitMsg};
		}

		if (!this.submitted)
		{
			formData = this._submitsetup(parms, false);
			DWREngine._execute("/resources/ajax/ajaxPanels.cfc" +
				this.settings.noauditparm, null, "submitCfc", formData,
				this.loadResponse.createDelegate(this));
		}
	},
	fnDownload: function(parms)
	{
		if (!this.submitted)
		{
			if (!parms)
			{
				parms = {action:""};
			}
			var formData = this._submitsetup(parms, true);
			formData._dl_ = "true";
			DWREngine._execute("/resources/ajax/ajaxPanels.cfc" +
				this.settings.noauditparm, null, "submitCfc", formData,
				this.loadResponse.createDelegate(this));
		}
	},
	fnDownloadDirect: function(parms)
	{
		var urlParms = "",form=document.forms[this.form],n;
		if (parms)
		{
			for (n in parms)
			{
				urlParms = urlParms + "&" + n + "=" + parms[n];
			}
		}
		clearUndisplayedFields(form);
		form.action = "/resources/ajax/ajaxPanels.cfc?method=downloadCfc&cfc=" +
			this.cfc + urlParms;
		form.method = "post";
		form.submit();
		form.action = "";
		form.method = "";

		if (!parms.keepsubmitlock)
		{
			this.clearSubmitLock();
		}
	},
	fnUpload: function(parms)
	{
		var formData;
		if (!this.submitted)
		{
			if (!parms)
			{
				parms = {action:""};
			}
			formData = this._submitsetup(parms, true);
			formData._ul_ = "true";
			DWREngine._execute("/resources/ajax/ajaxPanels.cfc" +
				this.settings.noauditparm, null, "submitCfc", formData,
				this.loadResponse.createDelegate(this));
		}
	},
	fnUploadDirect: function(parms)
	{
		var urlParms = "",that=this,form=document.forms[this.form],ifname,iframe,n;
		if (parms)
		{
			for (n in parms)
			{
				urlParms = urlParms + "&" + n + "=" + parms[n];
			}
		}
		ifname = ("uploader" + (new Date()).getTime());
		iframe = Ext.DomHelper.insertFirst(Ext.getBody(), {
			tag:"iframe", id:ifname, name:ifname, src:"about:blank",
			frameBorder:1, scrolling:"yes", height:"200", width:"600",
			style:"display:none;"});

		Ext.get(iframe).on("load", function() {
			var content;
			that.clearSubmitLock();
			content = trim(frames[ifname].document.body.innerHTML);
			setTimeout(function(){Ext.get(iframe).remove();}, 100);
			eval(base64Decode(content));
		});

		clearUndisplayedFields(form);
		form.action = "/resources/ajax/ajaxPanels.cfc?method=uploadCfc&cfc=" +
			this.cfc + urlParms;
		form.method = "post";
		form.target = ifname;
		form.enctype = "multipart/form-data";
		form.encoding = "multipart/form-data";
		form.submit();
		form.action = "";
		form.method = "";
		form.target = "";
		form.enctype = "text/plain";
		form.encoding = "text/plain";
	},
	loadResponse: function(resp)
	{
		if (resp.script && trim(resp.script).length > 0)
		{
			eval(resp.script);
		}
		else if (trim(resp.html).length > 0)
		{
			document.getElementById(this.form + "Div").innerHTML = resp.html;
			if (!this.cssLoaded)
			{
				applyEmbeddedCSS(resp.html);
				this.cssLoaded  = true;
			}

			if ('scriptconfigjss' in resp && trim(resp.scriptconfigjss).length > 0)
			{
				eval(resp.scriptconfigjss);
			}

			applyEmbeddedJS(resp.html);
			this.clearSubmitLock();
		}
	},
	_submitsetup: function(parms, carryOverParms)
	{
		var waitMsg,formData,n,button;

		if (!parms.action)
		{
			parms.action = "";
		}

		if (this.settings.waitmsgactive)
		{
			waitMsg = "Please Wait. . .";
			if (parms.waitMsg)
			{
				waitMsg = parms.waitMsg;
				delete parms.waitMsg;
			}
			this.showWaitMsg(waitMsg);
		}

		this.submitted = true;

		if (parms.button)
		{
			button = parms.button;
			delete parms.button;
			this.submitbtn = button;
			this.submitbtn.disabled = true;
		}

		formData = {};
		if (document.forms[this.form])
		{
			clearUndisplayedFields(document.forms[this.form]);
			formData = extractFormData(document.forms[this.form]);
		}
		formData.cfc=this.cfc;

		for (n in parms)
		{
			formData[n] = parms[n];
			// identify parms to be carried over on uploads and downloads
			if (carryOverParms)
			{
				formData["p$" + n] = parms[n];
			}
		}
		return formData;
	},
	clearSubmitLock: function()
	{
		if (this.settings.waitmsgactive)
		{
			this.hideWaitMsg();
		}
		this.submitted = false;
		if (this.submitbtn)
		{
			this.submitbtn.disabled = false;
			this.submitbtn = null;
		}
	},
	showWaitMsg: function(msg)
	{
		this.waitMask = new Ext.LoadMask(this.form + "Cont",
			{msg:msg, removeMask:true});
		this.waitMask.show();
	},
	hideWaitMsg: function()
	{
		if (this.waitMask)
		{
			this.waitMask.hide();
			delete this.waitMask;
		}
	},

	/*
	  Create the functions for popup mode even if not using popup mode
		if they are called they won't do anything unless this.settings.float is true
	*/
	show: function(parms)
	{
		var content, windowDefinition;

		if (this.settings.float)
		{
			if (!this.popupWin)
			{
				content = Ext.get(this.form + "Cont");
				content.show();
				windowDefinition = {
					width:       14 + content.getWidth(),
					closeAction: 'hide',
					items:       content,
					modal:       true,
					resizable:   false,
					bwrapCfg:    {cls: 'amerisave-hide-bwrap'}
				};

				if (this.settings.title)
				{
					windowDefinition.title = this.settings.title;
				}

				this.popupWin = new Ext.Window(windowDefinition);
			}

			this.popupWin.purgeListeners();

			// apply parameters (we can add more parms here later)
			if (parms)
			{
				/* title for popup win */
				if ('title' in parms)
				{
					this.popupWin.setTitle(parms.title);
				}

				/* element to set focus on after popup
					this isn't quite working right yet... need to figure out why... */

				if ('focus' in parms)
				{
					this.popupWin.on('show', function() {
						//setTimeout(function(){parms.focus.focus();},1000);
						parms.focus.focus();
					});
				}
			}

			this.popupWin.show();
			this.reposition();
		}
	},
	reposition: function()
	{
		var pos;
		if (this.popupWin)
		{
			this.popupWin.center();
			pos = this.popupWin.getPosition();
			if (pos[1] < 0)
			{
				this.popupWin.setPagePosition(pos[0], 0);
			}
		}
	},

	hide: function()
	{
		if (this.settings.waitmsgactive)
		{
			this.hideWaitMsg();
		}
		if (this.popupWin)
		{
			this.popupWin.hide();
		}
	},

	onKeyPress: function(e)
	{
		if(e.which == 13 || e.keyCode == 13)
		{
			var button = document.getElementById(this.settings.clickbtnidonenter);
			if (button)
			{
				button.click();
			}
			e.keyCode = 0;
		}
	}
});
