/**
 * ActiveSMSMailer
 * Provides active mailing functions to product template
 * @author Coolblue
 * @constructor
 * @param {Object} form The form object
 * @param {String} productName The name of the product
 * @param {Boolean} productPageModule Indicator if the module is used on the productpage or not.
 */
function ActiveSMSMailer(form, productName, productPageModule)
{
	// Private
	var self	= this,
		socket	= new Socket(),
		dom		= new DOM(),
		loading, error, completed, closeButton;

	// Public
	this.toggleActiveSMSMailer = toggleActiveSMSMailer;

	buildCheckbox();

	// Loading icon
	loading = dom.create(
		"div",
		{
			id : "product_activemailer_progress"
		},
		[
			"Een ogenblik a.u.b.",
			dom.create("br"),
			"je opdracht wordt verwerkt"
		]
	);

	/**
	 * Optional fields
	 * @requires OptionalFields Uses the OptionalFields constructor
	 * @method
	 */
	var optionalMobile = new OptionalFields(
		dom.getById("product_activemailer_mobilecontainer"),
		dom.getById("product_activemailer_sms"),
		dom.getById("product_activemailer_mobile")
	);

	/**
	 * Make a new Form
	 * @requires Form Uses the Form constructor
	 * @method
	 */
	var activeMailerForm	= new Form(dom.getById("activemailer_form")),
	activeMailerFormRows	= new FormRows(),
	activeMailerFormNotices	= new FormNotices(productPageModule);

	activeMailerForm.addEventListener(Form.FIELD_ADDED, activeMailerFormRows.add);
	activeMailerForm.addEventListener(Form.VALIDATION_COMPLETE, activeMailerFormNotices.update);

	/**
	 * Lastname
	 * @requires InputField
	 */
	var lastNameField = new InputField(dom.getById("product_activemailer_lastname"));

	if (productPageModule == true)
	{
		lastNameField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(" ", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + lastNameField.getElement().id, onclick: lastNameField.focus}, ["achternaam"]), " niet ingevuld"])));
	}
	else
	{
		lastNameField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " achternaam niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + lastNameField.getElement().id, onclick: lastNameField.focus}, ["achternaam"]), " niet ingevuld"])));
	}

	lastNameField.addEventListener(Field.VALIDATION_COMPLETE, activeMailerFormRows.update);
	activeMailerForm.addField(lastNameField);

	/**
	 * emailAddressField
	 * @requires InputField
	 */
	var emailAddressField = new InputField(dom.getById("product_activemailer_email"));

	if (productPageModule == true)
	{
		emailAddressField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(" ", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + emailAddressField.getElement().id, onclick: emailAddressField.focus}, ["e-mailadres"]), " niet ingevuld"])));
		emailAddressField.addRequirement(new FormatRequirement(FormatRequirement.EMAIL_ADDRESS, new Notice(" ", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + emailAddressField.getElement().id, onclick: emailAddressField.focus}, ["e-mailadres"]), " ingevuld"])));
	}
	else
	{
		emailAddressField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " e-mailadres niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + emailAddressField.getElement().id, onclick: emailAddressField.focus}, ["e-mailadres"]), " niet ingevuld"])));
		emailAddressField.addRequirement(new FormatRequirement(FormatRequirement.EMAIL_ADDRESS, new Notice(getVousOuTu("U heeft", "Je hebt") + " geen geldig e-mailadres ingevuld", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + emailAddressField.getElement().id, onclick: emailAddressField.focus}, ["e-mailadres"]), " ingevuld"])));
	}

	emailAddressField.addEventListener(Field.VALIDATION_COMPLETE, activeMailerFormRows.update);
	activeMailerForm.addField(emailAddressField);

	/**
	 * mobileNumberField
	 * @requires InputField
	 */
	var mobileNumberField = new InputField(dom.getById("product_activemailer_mobile"));

	if (productPageModule == true)
	{
		mobileNumberField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(" ", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + mobileNumberField.getElement().id, onclick: mobileNumberField.focus}, ["mobiele nummer"]), " niet ingevuld"])));

		if (controller.getParameter("areacode") == 31)
		{
			mobileNumberField.addRequirement(new ValidNLMobileTelephoneNumberRequirement(new Notice(" ", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + mobileNumberField.getElement().id, onclick: mobileNumberField.focus}, ["mobiel nummer"]), " ingevuld"])));
		}
		else if (controller.getParameter("areacode") == 32)
		{
			mobileNumberField.addRequirement(new ValidBEMobileTelephoneNumberRequirement(new Notice(" ", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + mobileNumberField.getElement().id, onclick: mobileNumberField.focus}, ["mobiel nummer"]), " ingevuld"])));
		}
	}
	else
	{
		mobileNumberField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " mobiele nummer niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + mobileNumberField.getElement().id, onclick: mobileNumberField.focus}, ["mobiele nummer"]), " niet ingevuld"])));

		if (controller.getParameter("areacode") == 31)
		{
			mobileNumberField.addRequirement(new ValidNLMobileTelephoneNumberRequirement(new Notice(getVousOuTu("U heeft", "Je hebt") + " geen geldig mobiel nummer ingevuld", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + mobileNumberField.getElement().id, onclick: mobileNumberField.focus}, ["mobiel nummer"]), " ingevuld"])));
		}
		else if (controller.getParameter("areacode") == 32)
		{
			mobileNumberField.addRequirement(new ValidBEMobileTelephoneNumberRequirement(new Notice(getVousOuTu("U heeft", "Je hebt") + " geen geldig mobiel nummer ingevuld", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + mobileNumberField.getElement().id, onclick: mobileNumberField.focus}, ["mobiel nummer"]), " ingevuld"])));
		}
	}

	mobileNumberField.addDependency(new VisibilityDependency(optionalMobile, mobileNumberField));
	mobileNumberField.addEventListener(Field.VALIDATION_COMPLETE, activeMailerFormRows.update);
	activeMailerForm.addField(mobileNumberField);

	socket.addEventListener(Socket.LOADED, function()
	{
		if (socket.getStatus() == 200) 
		{
			if (typeof urchinTracker != "undefined" && controller.getParameter("googleAnalyticsActionSubmitted")) 
			{
				urchinTracker(controller.getParameter("googleAnalyticsActionSubmitted"));
			}

			setTimeout(function() 
			{
				dom.getById("product_activemailer_form").removeChild(loading);
				dom.getById("product_activemailer_form").appendChild(completed);
			}, 750);
		}
	});


	/**
	 * Form onsubmit function
	 */
	form.onsubmit = function()
	{
		if (activeMailerForm.validate() == true)
		{
			if (productPageModule == false)
			{
				return true;
			}
			else if (dom.getById("product_activemailer_captcha"))
			{
				return true;
			}
			else
			{
				// Get the entered information, used in the 'completed' message and request
				var genderValue		 	= dom.getById("product_activemailer_m").checked ? "heer" : "mevrouw",
					lastNameValue	 	= dom.getById("product_activemailer_lastname").value,
					mobileNumberValue 	= dom.getById("product_activemailer_mobile").value,
					emailValue		 	= dom.getById("product_activemailer_email").value;
					newsletterValue		= dom.getById("product_activemailer_newsletter").checked ? "Y" : "N",
					productidValue		= dom.getById("product_activemailer_productid").value,
					shopidValue 		= dom.getById("product_activemailer_shopid").value,
					customeridValue		= dom.getById("product_activemailer_customerid").value,
					genderMFValue		= dom.getById("product_activemailer_m").checked ? "M" : "F";

				if (mobileNumberValue != "")
				{
					var mobileNumberFeedbackText = " en een SMS bericht op ";
					var mobileNumberFeedbackNumber = dom.create("strong", null, [" " + mobileNumberValue + ""]);
				}
				else
				{
					var mobileNumberFeedbackText = "";
					var mobileNumberFeedbackNumber = "";
				}
				
				dom.getById("product_activemailer_form").removeChild(dom.getById("activemailer_form"));

				// 'Completed' message
				completed = dom.create(
					"div",
					{
						id : "product_activemailer_completed"
					},
					[
						"Geachte " + genderValue + " " + lastNameValue + ",",
						dom.create("br"),
						dom.create("br"),
						"Hartelijk dank voor je inschrijving. ",
						"Zodra de " + productName + " op voorraad is ",
						getVousOuTu("ontvangt u ", "ontvang je "),
						"van ons automatisch een e-mail op",
						dom.create("strong", null, [" " + emailValue + ""]),
						mobileNumberFeedbackText,
						mobileNumberFeedbackNumber,
						".",
						dom.create(
						"div",
						{
							id : "product_activemailer_footer"
						},
						[
							dom.create(
								"button",
								{
									id			: "product_activemailer_reset",
									onclick		: reset
								}
							),
							closeButton
						]
					)
					]
				);

				//show loading icon
				dom.getById("product_activemailer_form").appendChild(loading);

				// The validator requires the request to be asynchronous, as other requirements may depend on the result of the request
				socket.request(
					form.action,
					{
						gender		: genderMFValue,
						lastname 	: lastNameValue,
						email 		: emailValue,
						mobile 		: mobileNumberValue,
						newsletter	: newsletterValue,
						productid	: productidValue,
						shopid		: shopidValue,
						customerid	: customeridValue,
						ajax		: true
					},
					true,
					true
				);
			}
		}
		return false;
	}


	/**
	 * Open or close the ActiveSMSMailer (toggle)
	 */
	function toggleActiveSMSMailer()
	{
		if (productPageModule == true)
		{
			if (dom.getById("product_activemailer").hasClass("alwaysvisible") == false)
			{
				dom.getById("product_activemailer").insertBefore(dom.create(
					"a",
					{
						id		: "product_activemailer_toggle",
						href	: "#product_activemailer_form",
						onclick	: function() {
									var toggle = dom.extend(this),
										target = dom.getById(toggle.href.substr(toggle.href.indexOf("#") + 1));

									if (target) 
									{
										if (toggle.hasClass("active")) 
										{
											toggle.removeClass("active");
											target.removeClass("active");
										}
										else
										{
											toggle.addClass("active");
											target.addClass("active");
										}
									}
									return false;
								}
					},
					[
						"E-mailadres opgeven"
					]
				), dom.getById("product_activemailer_form"));
		
				if (dom.getById("product_activemailer_form").hasClass("active"))
				{
					dom.getById("product_activemailer_toggle").addClass("active");
				}
			}
		}
	}


	/**
	 * Highlights rows onmouseover
	 */
	$(document).ready(function(){
		rowHighlighting($("#product_activemailer")); //Marijn edit: refactor and jquery solotion
	})

	/**
	 * Set focus to the first field on the page
	 */
	function firstFieldFocus()
	{
		if (dom.getById("product_activemailer_form"))
		{
			dom.getById("product_activemailer_m").focus();		
		}
	}

	/**
	 * Reset activeSMSmailer form
	 * @return {Boolean} false
	 */
	function reset()
	{
		dom.getById("product_activemailer_form").removeChild(completed);
		dom.getById("product_activemailer_form").appendChild(form, true);

		form.reset();

		if (dom.getById("product_activemailer_mobilecontainer").hasClass("active"))
		{
			dom.getById("product_activemailer_sms").checked = true;
		}
		else
		{
			dom.getById("product_activemailer_sms").checked = false;
		}

		// Reset validation
		mobileNumberField.resetValidation();
		mobileNumberField.setDisabled(true);
		lastNameField.resetValidation();
		emailAddressField.resetValidation();

		return false;
	}

	/**
	 * Toggles the opened form to close
	 * @return {Boolean} false
	 */
	function close()
	{
		dom.getById("product_activemailer_toggle").onclick();

		return false;
	}

	/**
	 * Build the form components
	 */
	function buildCheckbox()
	{

		//Checkbox for mobile number
		var checkbox = dom.create(
			"input",
			{
				id		: "product_activemailer_sms",
				name	: "sms",
				value	: "y",
				type	: "checkbox"
			}
		);

		//insert checkbox before sms label
		var parentDiv = dom.getById("product_activemailer_smscontainer");
		var label = parentDiv.getFirstByTagName("label");
		parentDiv.insertBefore(checkbox,label);

		//reused variables, insert asterix after labelvalue
		var requirementAsterix = dom.createText("*");
		parentDiv = dom.getById("product_activemailer_mobilecontainer");
		label = parentDiv.getFirstByTagName("label");
		label.appendChild(requirementAsterix);
	}

	/**
	 * initiate the formvalidation
	 */
	function FormRows()
	{
		var fields = {};

		this.add		= add;
		this.update		= update;
		this.loading	= loading;

		/**
		 * add field
		 * @event
		 * @param {Event} event
		 */
		function add(event)
		{
			if (event.target in fields == false && (event.target instanceof InputField || event.target instanceof SelectField || event.target instanceof DateField))
			{
				var field = (fields[event.target] = event.target);

				// Get the row
				field.row = dom.extend(field.getElement().parentNode);

				if (field.row.hasClass("validation") == false)
				{
					field.row.addClass("validation");

					// Create and append notifier
					field.notifier = dom.create("span", {className : "validation"}, [
						dom.create("img", {src : "/images/default/validation_neutral_icon.png"})
					]);

					field.row.appendChild(fields[field].notifier);

					// Set notices
					field.failedNotice = null;
					field.passedNotice = null;

					// Validate (if the field has a value)
					if ((event.target instanceof InputField || event.target instanceof SelectField || event.target instanceof DateField) && field.getElement().value != "")
					{
						field.validate(Field.VALIDATION_TRIGGER_FIELD_ADDED);
					}
				}
			}
		}

		/**
		 * Formvalidator update function
		 * @throws {UnknownField} Unknown field. 
		 * @event
		 * @param {Event} event
		 */
		function update(event)
		{
			var field = fields[event.target];

			if (field == undefined)
			{
				throw new Error("Unknown field.");
			}

			// If there's a notice present, remove it
			if (field.notifier.lastChild && field.notifier.lastChild.nodeType == 3)
			{
				field.notifier.removeChild(field.notifier.lastChild);
			}

			// Clear the classes, if present
			field.row.removeClass("failed");
			field.row.removeClass("passed");
	
			// Validation failed, update the notifier
			if (field.getValid() == false)
			{
				field.passedNoticeNotice = null;

				if (field.failedNotice == null || field.getValidationTrigger() == Field.VALIDATION_TRIGGER_BLUR || field.getValidationTrigger() == Field.VALIDATION_TRIGGER_CHANGE || field.getValidationTrigger() == Field.VALIDATION_TRIGGER_SUBMIT)
				{
					if (field.getFailedNotice() != null)
					{
						field.failedNotice = field.getFailedNotice().getPlainText();
					}
				}

				field.row.addClass("failed");

				field.notifier.getFirstByTagName("img").src = "/images/default/validation_failed_icon.png";

				if (field.failedNotice != null)
				{
					field.notifier.appendChild(dom.createText(field.failedNotice));
				}
			}
			// Passed validation
			else if (field.getValid() == true)
			{
				field.failedNotice = null;

				if (field.getPassedNotice() != null)
				{
					field.passedNotice = field.getPassedNotice().getPlainText();
				}

				field.row.addClass("passed");

				field.notifier.getFirstByTagName("img").src = "/images/default/validation_passed_icon.png";

				if (field.passedNotice != null)
				{
					field.notifier.appendChild(dom.createText(field.passedNotice));
				}
			}
			// No validation required
			else if (field.getValid() == null)
			{
				field.notifier.getFirstByTagName("img").src = "/images/default/validation_neutral_icon.png";
			}
		}

		/**
		 * Adds or removes a loading class to a field
		 * @event
		 * @param {Event} event
		 * @throws {Unknown Field} Unknown field.
		 */
		function loading(event)
		{
			var field = fields[event.target];

			if (field == undefined)
			{
				throw new Error("Unknown field.");
			}

			if (event.type == Field.VALIDATION_STARTED)
			{
				field.row.addClass("loading");
			}
			else if (event.type == Field.VALIDATION_COMPLETE)
			{
				field.row.removeClass("loading");
			}
		}
	}


	/**
	 * Formvalidator update function
	 * @param {Boolean} productPageModule Indicator if the module is used on the productpage or not.
	 */
	function FormNotices(productPageModule)
	{
		// Private
		var list = dom.create("ul", {id : "activemailer_validationerrors"});

		// Public
		this.update = update;

		//clear errorlist
		function clear()
		{
			list.remove();
	
			while (list.firstChild) 
			{
				list.removeChild(list.firstChild);
			}
		}

		//on update make error list if notices exist
		function update(event)
		{
			clear();

			var notices = event.target.getFailedNotices();

			if (notices.length > 0)
			{
				for (var i = 0; i < notices.length; i++)
				{
					list.appendChild(dom.create("li", null, notices[i].getHTML()));
				}

				var parentContainer = dom.getById("product_activemailer_submit");
				parentContainer.insertBefore(list,dom.getById("product_activemailer_send"));
			}
		}
	}
}



/**
 * OptionalFields
 * @constructor
 * @inherits EventDispatcher
 * @throws {InvalidArgument} targetElement is missing or not a DOM node.
 * @throws {InvalidArgument} triggerElement is missing.
 * @throws {InvalidArgument} focusElement is missing or not a DOM node.
 * @param {Object} targetElement the target element
 * @param {Object} triggerElement the trigger element
 * @param {Object} focusElement the element that gets the focus
 */
function OptionalFields(targetElement, triggerElement, focusElement)
{
	var dom		= new DOM();
	// Call the prototype's constructor
	EventDispatcher.call(this);

	// Check arguments
	if (targetElement == undefined || targetElement.nodeType == undefined || targetElement.nodeType != 1)
	{
		throw new Error("Invalid argument: targetElement is missing or not a DOM node");
	}

	if (triggerElement == undefined)
	{
		throw new Error("Invalid argument: triggerElement is missing");
	}

	if (focusElement == undefined || focusElement.nodeType == undefined || focusElement.nodeType != 1)
	{
		throw new Error("Invalid argument: focusElement is missing or not a DOM node");
	}

	// Public
	this.getVisible			= getVisible;
	this.getTargetElement	= getTargetElement;

	// Private
	var self	= this,
		visible	= null;

	// On instantation
	dom.extend(targetElement);
	dom.extend(focusElement);
	
	triggerElement.onclick = (function()
	{
		return function()
		{
			if (triggerElement.checked == true)
			{
				self.dispatchEvent(new CustomEvent(OptionalFields.FIELD_VISIBLE, self));
			}
			else
			{
				self.dispatchEvent(new CustomEvent(OptionalFields.FIELD_HIDDEN, self));
			}

			setVisible(triggerElement.checked);
		}
	})();

	/**
	 * Show or hide the target element
	 * @param {Boolean} value Whether the target element should be visible.
	 * @throws {InvalidArgument} visible is missing or not a boolean.
	 */
	function setVisible(value)
	{
		if (typeof value != "boolean")
		{
			throw new Error("Invalid argument: visible is missing or not a boolean");
		}

		if (value == true)
		{
			targetElement.addClass("active");

			focusElement.focus();
		}
		else
		{
			targetElement.removeClass("active");
			focusElement.value = "";
		}

		visible = value;
		dom.getById("product_activemailer").style.visibility = "hidden";
		dom.getById("product_activemailer").style.visibility = "visible";
	}

	/**
	 * Returns if the element is visible or not
	 * @return {Boolean} visible The visible element true/false
	 */
	function getVisible()
	{
		return visible;
	}

	/**
	 * Returns the target element
	 * @return {Object} targetElement The target element
	 */
	function getTargetElement()
	{
		return targetElement;
	}
}

// Inheritance
OptionalFields.prototype = new EventDispatcher();

/** @constant */
OptionalFields.FIELD_VISIBLE	= "field_visible";
/** @constant */
OptionalFields.FIELD_HIDDEN		= "field_hidden";

