(function($){  
  
    $.fn.extend({   
          
        //pass the options variable to the function  
        DreamForm: function(rowModel, options) {  
  
            var app_path = window.location.href.substring(0, window.location.href.lastIndexOf("/")+1);
            var $form = this;
			var validate = true;

			//Set the default values, use comma to separate the settings, example:  
            var defaults = {
				u: "/code/forms/1.0.1/php/", //+"email.php"
				txtSubmit: 'Submit',
				shipping: false
			};
            var options =  $.extend(defaults, options);  
			
			//Public Functions			
			this.checkForm = function(target) {
			
				$(".errormsg", target).hide();
					
				//		  /^4[0-9]{12}([0-9]{3})?$/ 'Visa';
				//		  /^5[1-5][0-9]{14}$/ 'Master Card';
				//		  /^3[47][0-9]{13}$/ 'American Express';
				//		  /^3(0[0-5]|[68][0-9])[0-9]{11}$/ 'Diners Club';
				//		  /^6011[0-9]{12}$/ 'Discover';
				//		  /^6[0-9]{18}$/ 'Laser/Maestro/Electron';
				//		  /^6[0-9]{15}$/ 'Laser';
				
				// This breaks internet explorer - the fact that it's not a string
				var v = { 
					v_number: /^[\d]+$/, 
					v_phone: /^(\+|0)[\d]{8,13}$/, 
					v_firstname: /^([a-z]+(\'|-|\.\s|\s)?[a-z]*){1,2}$/i,
					v_surname: /^([a-z]+(\'|-|\.\s|\s)?[a-z]*){1,2}$/i,
					v_email: /^(([A-Z0-9]+_+)|([A-Z0-9]+\-+)|([A-Z0-9]+\.+)|([A-Z0-9]+\++))*[A-Z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[A-Z]{2,6}$/i,
					v_url: /^([A-Z0-9]([A-Z0-9\-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}$/i,
					v_address: /^(\w(\s|\.|\.\s|,|,\s)?)+$/,
					v_ccn: /^((4\d{3})|(5[1-5]\d{2})|(6011))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}|6\d{15}|6\d{17}|6\d{18}$/,
					v_ccv: /^\d{3}$/,
					v_cce: /^((0[1-9])|(1[0-2]))\/20(\d{2})$/,
					v_cc_em: /^(([1-9])|(0[1-9])|(1[0-2]))$/,
					v_cc_ey: /^20(\d{2})$/
				}; //' Comment to correct colour coding
	
				validate = true;			
				$.each(v, function(i, val) {
					$(":input."+i, target).removeClass("error").filter(function() {
						var valid = $(this).val().match(val); 
						if ($(this).val() == "") { valid=false; }
						if ( valid && ($(this).hasClass('v_ccn')) ) { valid = ccn_check($(this).val()); }
						return (!valid); 
					}).addClass("error").each(function() { validate = false; });	
				});
				$(target).children("label").removeClass("error");
				$(".formrow.error").removeClass("error");
				$(":input.error", target).parents(".formrow").addClass("error"); 
				
				if ( $(this).hasClass("error") ) {
					$("label.required[for='"+$(this).attr('id')+"']").fadeIn("slow"); 
				}

				else $form.removeClass("valid");
				
				return validate;
					
			}

			this.closeForm = function() {

				var o = options;
				var $f = $(this).parents("form:first");
				if ($(this).is("form")) $f = $(this);
				$f.append( $("<input type='submit' value='"+o.txtSubmit+"' />") );
				if ($f.hasClass("secureme")) secureform($f);
					
			}
			
			//Private Functions
			dreamDonate = function($t) {

				//Set the default values, use comma to separate the settings, example:  
				var o = options;
				
				$t.append("<table><tr><td class='Panel'><div class='Billing PanelHead ui-corner-all'><h1>Billing Address</h1><input class='showShipping' type='checkbox' checked='true'>"+
					"<label class='checkbox'>My Billing Address and Shipping Address are the same</label><small>Click to reveal Billing Address</small></div>"+
					"<div class='Billing Panel'><small class='ui-corner-all'>Fill in the billing details first! "+
					"For your convenience we will use details entered here to "+
					"automatically complete as much of the rest of the form as it can. "+
					"<font color='#CC0000'>Fields/Labels highlighted in red must be completed.</font>"+
					"</small></div>"+
					"<div class='Shipping PanelHead ui-corner-all'><h1>Shipping Address</h1><small>Click to reveal Shipping Address</small></div><div class='Shipping Panel'>"+
					"<small class='ui-corner-all'>Details will be automatically copied here from billing for your convenience.</small></div></td>"+
					"<td class='Panel Right'><div class='PanelHead ui-corner-all'><h1>Payment Details</h1></div><div class='Payment Panel'>"+
					"<small class='ui-corner-all'>For your convenience the name and surname will be automatically copied here from "+
					"the billing details entered above.</small></div></td></tr></table>");
					
				$(".PanelHead small", $t).hide(); 
				$(".Shipping", $t).slideUp();
				$(".showShipping").change(function () { 
					if ($(this).is(":checked")) {
						$(".Shipping").slideUp("slow"); 
						$(".Billing").slideDown("slow"); 
						$(".PanelHead small").hide(); 
					} else {
						$(".Billing.Panel").slideUp("slow"); 
						$(".Shipping").slideDown("slow"); 
						$(".PanelHead small").show(); 
					}
				});
				$(".Billing.PanelHead").click(function() {
					$(".Billing.Panel").slideDown("slow"); $(".Shipping.Panel").slideUp("slow"); 
				});
				$(".Shipping.PanelHead").click(function() {
					$(".Shipping.Panel").slideDown("slow"); $(".Billing.Panel").slideUp("slow"); 
				});
				
				if (!o.shipping){
					$(".showShipping").next().remove();
					$(".showShipping").remove();
				}
				
				var b = { 
					"bill_name": { label: "Name", class_name: "v_firstname"/*, value: "Philip" */ }, 
					"bill_surname": { label: "Surname", class_name: "v_surname"/*, value: "Nixon" */ },
					"bill_street": { label: "Street", class_name: "v_address", err: "Please enter a valid street address"/*, value: "17 Ryebridge Avenue" */ },
					"bill_street2": { label: "", hint: "Optional extra street address" },
					"bill_city": { label: "Town/City", class_name: "v_address", err: "Please enter a valid city name"/*, value: "Kilcock" */},
					"bill_county": { label: "County / State", class_name: "v_address", err: "Please enter a valid county name"/*, value: "Kildare" */ },
					"bill_country": { label: "Country", value: "Ireland" /*, class_name: "v_address", err: "Please enter a valid country name"*/ },
					"bill_phone": { label: "Phone"/*, class_name: "v_phone"*/ },
					"bill_email": { label: "Email", class_name: "v_email"/*, value: "dreamsedge@gmail.com" */ }
				};
				var s = { 
					"ship_name": { label: "Name"/*, class_name: "v_firstname"*/ }, 
					"ship_surname": { label: "Surname"/*, class_name: "v_surname"*/ },
					"ship_street": { label: "Street"/*, class_name: "v_address", err: "Please enter a valid street address"*/ },
					"ship_street2": { label: ""/*, hint: "Optional extra street address"*/ },
					"ship_city": { label: "City"/*, class_name: "v_address", err: "Please enter a valid city name"*/ },
					"ship_county": { label: "County / State"/*, class_name: "v_address", err: "Please enter a valid county name"*/ },
					"ship_country": { label: "Country", value: "Ireland"/*, class_name: "v_address", err: "Please enter a valid country name"*/ },
					"ship_phone": { label: "Phone"/*, class_name: "v_phone"*/ },
					"ship_email": { label: "Email"/*, class_name: "v_email"*/ }
				};
				var d = new Date();
				var m = d.getMonth()+1; if (m < 10) m = "0"+m;
				var dd = m+"/"+d.getFullYear();
				var p = { 
					"cctype": { label: "Type", type: "select", options: { VISA: 'Visa', MASTERCARD: 'Mastercard', LASER: 'Laser', DISCOVER: 'Discover', AMEX: "American Express" } }, 
					"ccname": { label: "Name"/*, class_name: "v_firstname"*/ }, 
					"ccsurname": { label: "Surname"/*, class_name: "v_surname"*/ },
					"ccnumber": { label: "Credit Card Number", class_name: "v_ccn"/*, value: "4111111111111111" */ },
					"ccv": { label: "CCV/CVV", class_name: "v_ccv"/*, value: "111" */ },
			
			"ccexpiry_month": { label: "Expiry Month", type: "select", class_name: "v_cc_em", options: { 'null' : 'Select Month', 01: 'January', 02: 'Februrary', 03: 'March', 04: 'April', 05: "May", 06: "June", 07: "July", 08: "August", 09: "September", 10: "October", 11: "November", 12: "December" } }, 
					"ccexpiry_year": { label: "Expiry Year", type: "select", class_name: "v_cc_ey", options: { } }
				};
				var d = new Date(); var curr_year = d.getFullYear();
				p.ccexpiry_year.options['null'] = 'Select Year';
				for(var i=0;i<10;i++) { p.ccexpiry_year.options[curr_year+i] = curr_year+i}
			
				if ($().DreamForm) {
					var $p = $(".Payment.Panel", $t).DreamForm(p);
					var $b = $(".Billing.Panel", $t).DreamForm(b);
					var $s = $(".Shipping.Panel", $t).DreamForm(s);
				}
				
				$b.find(":input").change(function () { 
				
					var bf = $(this).attr('id').substr(5);
			
					var empty_check = true;
					
					if ( (empty_check) && (!$(this).hasClass("error")) ) {
						$(".Shipping #ship_"+bf).val($(this).val()); 
						$s.checkForm(".Shipping");
					}
					if ((bf=="name")&&($(".Payment #ccname").val()=="")&&(!$(this).hasClass("error"))) {
						$(".Payment #ccname").val($(".Billing #bill_name").val()); 
						$p.checkForm(".Payment");
					} else if ((bf=="surname")&&($(".Payment #ccsurname").val()=="")&&(!$(this).hasClass("error"))) {
						$(".Payment #ccsurname").val($(".Billing #bill_surname").val()); 
						$p.checkForm(".Payment");
					}
					
				});
				
			}
			
			secureform = function($f) {

				$f.removeClass("secureme").addClass("secureForm");
				var o = options;
				if ($f.length > 0) {
					$('.warning').remove();
					$.get(o.u+"email.php", { request: null }, function(txt){ 
						$f.append('<input type="hidden" id="ts" name="ts" value="'+txt+'" />'); 
					});
					$f.unbind('submit').submit( function(event) {
						event.preventDefault();
						$('.warning').remove();
						if ($(":input.error").length > 0) {
							$(":submit",$f).before( $("<p />").addClass("warning ui-corner-all").html("Required information is missing in your form.<br />Please check the fields highlighted in red!") );
						} else {
							var data = $(":input", $f).serialize(); //alert(o.u+"email.php");
							$.post(o.u+"email.php", data, function(txt) { $(":submit",$f).before( $("<p />").addClass("warning ui-corner-all").html(txt) ); });
						}
					});
					$(":input", $f).click(function () { $(".warning", $f).remove(); });
				}
			}

			drawForm = function(target, rowModel) {
			
				var o = options;
				$.each(rowModel, function(i, val) { 
		
					var emsg = val.err, hmsg = val.hint;
					switch(val.class_name) {
						case "v_firstname":
							if (typeof(hmsg) === 'undefined') 
								hmsg = "A valid name is at least 1 character long and contains no digits";
							if (typeof(emsg) === 'undefined') emsg = "This does not appear to be a valid first name";
							break;
						case "v_surname":
							if (typeof(hmsg) === 'undefined') 
								hmsg = "A valid name is at least 1 character long and contains no digits";
							if (typeof(emsg) === 'undefined') emsg = "This does not appear to be a valid last name";
							break;
						case "v_email":
							if (typeof(emsg) === 'undefined')
								emsg = "This does not appear to be a valid email address";
							break;
						case "v_phone":
							if (typeof(hmsg) === 'undefined') 
								hmsg = "An area code (starting with '0') is required. Please use digits only - no spaces, dashes or brackets. '+' and country code (353 for ireland) are optional.";
							if (typeof(emsg) === 'undefined') emsg = "This does not appear to be a valid phone number";
							break;
						case "v_number":
							if (typeof(emsg) === 'undefined') emsg = "This does not appear to be a valid number";
							break;
						case "v_ccn":
							if (typeof(emsg) === 'undefined') emsg = "This does not appear to be a valid credit card number. Please use digits only - no spaces or dashes.";
							break;
						case "v_ccv":
							if (typeof(emsg) === 'undefined') emsg = "Please enter a valid ccv number. For Visa/Mastercard, the three-digit CVV number is printed on the signature panel on the back of the card immediately after the card's account number.";
							break;
						case "v_cce":
							if (typeof(emsg) === 'undefined') emsg = "Format mm/yyyy";
							break;
						case "v_cc_em":
							if (typeof(emsg) === 'undefined') emsg = "Please select a valid month";
							break;
						case "v_cc_ey":
							if (typeof(emsg) === 'undefined') emsg = "Please select a valid year";
							break;
						default:
					}
		
					var optns = "";
					var typ = val.type; if (typ === undefined) typ = "text";
					var vv = val.value; if (vv === undefined) vv = ""; else optns= "value='"+vv+"'";
					var vl; if (val.label == "") vl = "&nbsp;"; else vl = val.label;
					if ((typ == 'checkbox') && (vv == 'checked')) optns = " checked='checked' ";
					if ((typ == 'select') && (vv == 'checked')) optns = " checked='checked' ";
					var id = i; if (typeof val.id != 'undefined') id = val.id;
					
					var thisrow = $(target); var cl = "";
					if ((typeof val.class_name != 'undefined') || (typeof val.hint != 'undefined')) {
						$(target).append("<div class='formrow'><label for='"+id+"' class='field_label'>"+vl+"</label></div>");
						thisrow = $(target).find("div:last");
						cl = "class='"+val.class_name+"'";
					} else {
						$(target).append("<div class='formrow'><label for='"+id+"'>"+vl+"</label></div>");
						thisrow = $(target).find("div:last");
					}
					
					if (val.class_name !== undefined)
						$(thisrow).append("<label for='"+id+"' class='required'>You must supply a valid "+vl+"</label><br />");

					if (typ == "select") {
						$(thisrow).append("<select id='"+id+"' name='"+id+"' "+cl+optns+"></select>");
						$.each(val.options, function(key, opt) {
							var s = (key == "null") ? " selected=selected" : "";
							key = (key == "null") ? "" : key;
							$("<option value='"+key+"'"+s+">"+opt+"</option>").appendTo("#"+i, thisrow);
						});
					} else if (typ == "textarea") {
						$(thisrow).append("<textarea id='"+id+"' name='"+id+"' "+cl+optns+">"+vv+"</textarea>");
					} else {
						$(thisrow).append("<input id='"+id+"' name='"+id+"' value='"+vv+"' "+cl+" type='"+typ+"'"+optns+"/>");
					}
					
					if (typeof(hmsg) !== 'undefined') 
						$(thisrow).append("<label for='"+id+"' class='hint'>"+hmsg+"</label>");
					if (typeof(emsg) !== 'undefined') 
						$(thisrow).append("<label for='"+id+"' class='errormsg'>"+emsg+"</label>");
				});
		
				$(".formrow", target).addClass("ui-corner-all");
				$("label.hint").fadeOut("fast"); 
				
				$(":input", target).each( function () { 
					$.data(this, "focused", false); 
				}).focus( function () {
					$.data(this, "focused", true);
					$("label.hint[for='"+$(this).attr('id')+"']").fadeIn("slow"); 
				}).blur( function () {
					$form.checkForm($($form));
					$.data(this, "focused", false); 
					$("label.hint[for='"+$(this).attr('id')+"']").fadeOut("slow"); 
					if ( $(this).hasClass("error") ) {
						$("label.required[for='"+$(this).attr('id')+"']").fadeIn("slow"); 
						$("label.errormsg[for='"+$(this).attr('id')+"']").fadeIn("slow"); 
					} else {
						$("label.required[for='"+$(this).attr('id')+"']").fadeOut("slow"); 
						$("label.errormsg[for='"+$(this).attr('id')+"']").fadeOut("slow"); 
					}
				});
		
				return $(target);
			}

			ccn_check = function (ccNumb) {
				
				var len = ccNumb.length;
				var iCCN = parseInt(ccNumb);  // integer of ccNumb	
				var iTotal = 0;  // integer total set at zero
				var bNum = true;  // by default assume it is a number
				var bResult = false;  // by default assume it is NOT a valid cc
				var calc;  // used for calculation of each digit
				
				if ( (ccNumb.substr(0,4) != "6011") && (ccNumb.substr(0,1) == "6") ) {
					$("#cctype").val("LASER"); bResult = true;
					$("#ccv").val("000"); bResult = true;
				} else {
					if ($("#ccv").val() == "000") $("#ccv").val(""); 
					if ( (ccNumb.substr(0,1) == "4") ) $("#cctype").val("VISA");
					else if ( (ccNumb.substr(0,1) == "5") ) $("#cctype").val("MASTERCARD");
					else if ( (ccNumb.substr(0,4) == "6011") ) $("#cctype").val("DISCOVER");
					else if ( (ccNumb.substr(0,2) == "34") || (ccNumb.substr(0,2) == "37") ) 
						$("#cctype").val("AMERICAN EXPRESS");
					
					for(var i=len;i>0;i--){  // LOOP throught the digits of the card
					  calc = parseInt(iCCN) % 10;  // right most digit
					  calc = parseInt(calc);  // assure it is an integer
					  iTotal += calc;  // running total of the card number as we loop - Do Nothing to first digit
					  i--;  // decrement the count - move to the next digit in the card
					  iCCN = iCCN / 10;                               // subtracts right most digit from ccNumb
					  calc = parseInt(iCCN) % 10 ;    // NEXT right most digit
					  calc = calc *2;                                 // multiply the digit by two
					  // I use a simple switch statement to change the value of calc2 to 7 if 16 is the multiple.
					  switch(calc){
						case 10: calc = 1; break;       //5*2=10 & 1+0 = 1
						case 12: calc = 3; break;       //6*2=12 & 1+2 = 3
						case 14: calc = 5; break;       //7*2=14 & 1+4 = 5
						case 16: calc = 7; break;       //8*2=16 & 1+6 = 7
						case 18: calc = 9; break;       //9*2=18 & 1+8 = 9
						default: calc = calc;           //4*2= 8 &   8 = 8  -same for all lower numbers
					  }                                               
					  iCCN = iCCN / 10;  // subtracts right most digit from ccNum
					  iTotal += calc;  // running total of the card number as we loop
					}  // END OF LOOP
					if ((iTotal%10)==0){  // check to see if the sum Mod 10 is zero
					  bResult = true;  // This IS (or could be) a valid credit card number.
					} else {
					  bResult = false;  // This could NOT be a valid credit card number
					}
				}
				return bResult;
			}
			
			return this.each(function() {
				var o = options; 
                var obj = $(this);

				var $f = $(this).parents("form:first");
				if ($(this).is("form")) $f = $(this);
				
                $f.addClass("DreamForm");  
				if (rowModel === undefined) { dreamDonate($f); }
				else drawForm(this, rowModel); 
				if ($.browser.msie && $.browser.version <= 7) $(":input:first", obj).focus();
				$form.checkForm(obj);
				$(":input",this).change(function () { $form.checkForm(obj); });
//				$(":input",this).blur(function () { $form.checkForm(obj); });
			});
			

		}
	});
})(jQuery);
