/**
 * ReviewMailer constructor
 * @constructor
 * @param {Object} form The review mailer form object
 */
function ReviewMailer(form)
{
	// Private
	var self	= this,
		socket	= new Socket(),
		dom		= new DOM(),
		regexpInternalWhitespace = /\s\s+/g,
		formcontainer = dom.getById("review_add");

	/**
	 * Trim function 
	 * @param {String} value
	 * @return {String} value
	 * @method
	 */
	function trim(value) 
	{
	  value = value.replace(/^\s+/,'');
	  value = value.replace(/\s+$/,'');
	  return value;
	}


	/**
	 * reviewMailerForm
	 * @method
	 * @requires Form
	 */
	var reviewMailerForm	= new Form(form),
	reviewMailerFormRows	= new FormRows(),
	reviewMailerFormNotices	= new FormNotices();

	reviewMailerForm.addEventListener(Form.FIELD_ADDED, reviewMailerFormRows.add);
	reviewMailerForm.addEventListener(Form.VALIDATION_COMPLETE, reviewMailerFormNotices.update);

	/**
	 * Adds name reviewer Field
	 * @requires InputField
	 */
	var reviewerNameField = new InputField(dom.getById("reviewername"));
		reviewerNameField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " naam niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + reviewerNameField.getElement().id, onclick: reviewerNameField.focus}, ["naam"]), " niet ingevuld"])));
		reviewerNameField.addEventListener(Field.VALIDATION_COMPLETE, reviewMailerFormRows.update);
		reviewMailerForm.addField(reviewerNameField);

	/**
	 * Adds email Field
	 * @requires InputField
	 */
	var emailAddressField = new InputField(dom.getById("revieweremail"));
		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, reviewMailerFormRows.update);
		reviewMailerForm.addField(emailAddressField);
		
	var ratingFields = dom.getById("ratings").getElementsByTagName("input");

	for (var i = 0; i < ratingFields.length; i++)
	{
		ratingName = ratingFields[i].parentNode.parentNode.id;
		ratingName.replace("_", " ");
		ratingId = ratingFields[i].id;

		/**
		 * Adds rating Field
		 * @requires InputField
		 */
		var ratingField = new InputField(dom.getById(ratingId));
			ratingField.addRequirement(new FormatRequirement(FormatRequirement.NOT_ZERO, new Notice("", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " beoordeling bij '", ratingName, "' niet ingevuld"])));
			ratingField.addEventListener(Field.VALIDATION_COMPLETE, reviewMailerFormRows.update);
			reviewMailerForm.addField(ratingField);
	}

	/**
	 * Adds title Field
	 * @requires InputField
	 */
	var titleField = new InputField(dom.getById("reviewtitle"));
		titleField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " geen titel ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + " geen ", dom.create("a", {href : "#" + titleField.getElement().id, onclick: titleField.focus}, ["titel"]), " ingevuld"])));
		titleField.addEventListener(Field.VALIDATION_COMPLETE, reviewMailerFormRows.update);
		reviewMailerForm.addField(titleField);


	/**
	 * Wordcounter for input field
	 * Counts the number of words in the input textarea. Also count characters
	 * @method
	 * @param inputElement {Object} The input element
	 */
	function WordCounter(inputElement)
	{
		var wordCount = 0;

		count();
		this.getCount = getCount;

		dom.extend(inputElement).addEventListener("keyup", count, true);

		function count()
		{
			var charCount = inputElement.value.length;
			var wordCounterString = trim(inputElement.value);

			if (charCount == 0)
			{
				wordCount = 0;
			}
			else
			{
				wordCounterString = wordCounterString.replace(regexpInternalWhitespace, " ")
				wordCount = (wordCounterString.split(/\s/).length);
			}

			clearWordCount = dom.create(
				"p",
				{
					id: "wordcount_error"
				}
			);
		
			WordCountZeroError = dom.create(
				"p",
				{
					id: "wordcount_error"
				},
				[
					"Minimaal ",
					dom.create(
						"strong",
						null,
						["20"]
					),
					" woorden."
				]
			);

			if(charCount < 40000)
			{
				// Format wordcount counter messages
				counterMessage = dom.create(
					"p",
					{
						id: "wordcount_single"
					},
					[
						getVousOuTu("U heeft", "Je hebt") + " reeds ",
						dom.create(
							"strong",
							null, 
							[wordCount]
						),
						" woord(en)."
					]
				);
			}
			else
			{
				// Format wordcount counter messages
				counterMessage = dom.create(
					"p",
					{
						id: "wordcount_single"
					},
					[
						getVousOuTu("U heeft", "Je hebt") + " ",
						dom.create(
							"strong",
							null, 
							[charCount]
						),
						" karakters."
					]
				);
			}

			var parent = dom.getById("wordcounter");
			var container = dom.getById("wordcounter").getFirstByTagName("p");

			if (wordCount < 20)
			{
				parent.replaceChild(WordCountZeroError,container);
				container = dom.getById("wordcounter").getFirstByTagName("p");
				container.appendChild(counterMessage);
			}
			else
			{
				parent.replaceChild(clearWordCount,container);
				container = dom.getById("wordcounter").getFirstByTagName("p");
				container.appendChild(counterMessage);
			}
		}

		function getCount()
		{
			return wordCount;
		}
	}

	WordCounter.prototype = new Requirement();

	/**
	 * Adds motivation Field
	 * @field
	 * @requires InputField
	 */
	var motivationField = new InputField(dom.getById("reviewtext"), new Notice('Minimaal 20 woorden'));
		motivationField.addRequirement(new MinLengthRequirement(new WordCounter(dom.getById("reviewtext")), 20, new Notice(getVousOuTu("Uw", "Je") + " motivatie dient uit minimaal 20 woorden te bestaan", [getVousOuTu("Uw", "Je") + " ", dom.create("a", {href : "#" + motivationField.getElement().id, onclick: motivationField.focus}, ["motivatie"]), " dient uit minimaal 20 woorden te bestaan"])));
		motivationField.addRequirement(new MaxLengthRequirement(40000, new Notice(getVousOuTu("U heeft", "Je hebt") + " meer dan 40.000 karakters in " + getVousOuTu("uw", "je") + " motivatie", [getVousOuTu("U heeft", "Je hebt") + " " + " meer dan 40.000 karakters in "+ getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + motivationField.getElement().id, onclick: motivationField.focus}, ["motivatie"])])));
		motivationField.addEventListener(Field.VALIDATION_COMPLETE, reviewMailerFormRows.update);
		reviewMailerForm.addField(motivationField);
		
	/**
	 * Adds pros Field
	 * The maximum number of characters allowed in the review_add_pros_cons element
	 * @field
	 * @requires InputField
	 */
	var prosField = new InputField(dom.getById("reviewpros"), new Notice(''));
		prosField.addRequirement(new MaxLengthRequirement(3900, new Notice(getVousOuTu("U heeft", "Je hebt") + " meer dan 4.000 karakters in " + getVousOuTu("uw", "je") + " pluspunten", [getVousOuTu("U heeft", "Je hebt") + " " + " meer dan 4.000 karakters in "+ getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + prosField.getElement().id, onclick: prosField.focus}, ["pluspunten"])])));
		prosField.addEventListener(Field.VALIDATION_COMPLETE, reviewMailerFormRows.update);
		reviewMailerForm.addField(prosField);

	/**
	 * Adds cons Field
	 * The maximum number of characters allowed in the review_add_pros_cons element
	 * @field
	 * @requires InputField
	 */
	var consField = new InputField(dom.getById("reviewcons"), new Notice(''));
		consField.addRequirement(new MaxLengthRequirement(3900, new Notice(getVousOuTu("U heeft", "Je hebt") + " meer dan 4.000 karakters in " + getVousOuTu("uw", "je") + " minpunten", [getVousOuTu("U heeft", "Je hebt") + " " + " meer dan 4.000 karakters in "+ getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + consField.getElement().id, onclick: consField.focus}, ["minpunten"])])));
		consField.addEventListener(Field.VALIDATION_COMPLETE, reviewMailerFormRows.update);
		reviewMailerForm.addField(consField);

	/**
	 * Form onsumbit function
	 * @field
	 * @requires form
	 */
	form.onsubmit = function()
	{
		if (reviewMailerForm.validate() == true)
		{
			if (typeof urchinTracker != "undefined" && controller.getParameter("utm_campaign") && controller.getParameter("utm_campaign") == "reviewincentive") 
			{
				urchinTracker("/reviewsent.html?page=" + _udl.pathname + _udl.search);
			}
			return true;
		}
		return false;
	}



	/**
	 * Highlights rows
	 * @method
	 */
	$(document).ready(function(){
		rowHighlighting($("#review_add form"))
	})


	/**
	 * Add or update form rows for reviewmailer
	 * @constructor
	 */
	function FormRows()
	{
		var fields = {};

		this.add		= add;
		this.update		= update;
		this.loading	= loading;

		/**
		 * Add fields
		 * @param {Event} 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);
					}
				}
			}
		}

		/**
		 * Update fields
		 * @param {Event} 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 loading class
		 * @param {Event} event
		 * @event
		 */
		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");
			}
		}
	}



	/**
	 * Show notices for reviewmailer
	 * @constructor
	 */
	function FormNotices()
	{
		// Private
		var list = dom.create("ul", {className : "errors"});

		// 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
		 * @param {Event} event
		 * @event
		 */
		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("review_send_button");
				parentContainer.insertBefore(list,dom.getById("review_send_button").getFirstByTagName("input"));
			}
		}
	}
}