// (C) 2003 Ken McCormack P21 www.p21.com.au //
/* 
User fields are defined as follows:

fields[etc] = new formElementObj (field_name,user_friendly_ name,validation_type,default_value,minimum_length, 
				maximum_length, empty_field_error_message,class_name,value_array); 
where
field_name = matches the name of the form field exactly
user_friendly_name = the user readable name of the field, for use in error messages, eg 'Email Address'
validation_type = type of validation required for the field; valid options are
	
	"string" - 	string will be required that is between minimum and maximum length
	"select" - 	requires a selected index of the lement fieldName to be between minimum and maximum length
	"email" - 	same as for string, but requires a valid email address
	"ccdate" - 	credit card date validation - this will look for a date of the form "xx-MM-YYYY".
				An error is returned if the date is empty or in th past. 
	"ccnumber"  credit card number vallidation - this uses a mod10 checkdigit sum to validate CC numbers

default_value	= the defult value passed into the rendered element - ie.e inner text of a text field, checkbox status etc

minimum length - minimum string length, numeric quantity or select index
				- for checkbox this is true or false for whether should be checked / unchecked
maximum length - minimum string length, numeric quantity or select index
				- for checkbox this is the checked value
				
empty field error message - the message generated when the specified field is empty; for example, a string validated 
	will generate the following error messages:

	fields[fields.length] = new formElementObj ("el1","Element 1","string",2,5,"Please enter Element 1);

	empty field - generates error prompt -  'Please enter Element 1'
	string, length 1 generates error  -		'Error - minimum length for Element 1 is 2 characters' 
	string, length 6 generates error  -		'Error - maximum length for Element 1 is 5 characters' 

	NB: When this field is omitted, the form element is no longer required by validation - i.e. it becomes an optional field
	Required fields receive an asterix.

class_name = the CSS class applied to the element
value_array = an array passed containing value-text pairs of select box OPTION elements

Note - fields will be validated in the order they are declared - this should be the same order as they are displayed on the HTML form
*/
bDebug = false;
function displayFields()
{
	// disply customer form fields as set by fields array

	for (var i=0; i<fields.length; i++)
	{	
		displaySingleField(fields[i],false);
	}	

}

function showSingleFormElement(fieldName)
{
	// search for index from form field name
	for (var i=0; i<fields.length; i++)
	{	
		if (fields[i].fieldName == fieldName) 
		{	
			displaySingleField(fields[i],"true"); return true; 
		}
		
	}	
}

function displaySingleField(formElmObj, fieldOnly)
{
		var formStr="";  // form element
		var requiredString = "";
		
		if (bDebug) alert ("Adding "+ formElmObj.fieldName + " type= " + formElmObj.typeRequired)
		if (formElmObj.onChangeAction != "")
		{
			var onChangeAction = " onChange=\"" + formElmObj.onChangeAction + "\"";	
		}
		
		switch (formElmObj.typeRequired)
		{
			case "string" 	:
			case "email" 	:
			case "numeric"	:
			case "ccnumber" :  	formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"text\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\"" + onChangeAction + "/>"; 
								break;
			
			case "password" :  	formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"password\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\"" + onChangeAction + "/>"; 
								break;
			
			case "file"		:	formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"file\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\"" + onChangeAction + "/>"; 
								if (formElmObj.maxValue != "")
									document.write("<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\""+ formElmObj.maxValue +"\">");
								break;
								
			case "select" 	: 	formStr="<select name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\"" + onChangeAction + ">" + selectOption(formElmObj.valueArray,formElmObj.defaultValue) + "</select>"; break; 
			
			case "ccdate" 	: 	// render hidden field where segmented fields are concatenated	
								formStr="<input type=\"hidden\" name=\""+ formElmObj.fieldName +"\" value=\"00-00-0000\">";
								// render segmeted fields and onchange events calling updateDate function, which updates hidden 'parent' element above
								formStr+= "Month: " + splitCCDateSelectElement("cc_expiry_month",formElmObj.fieldName,"month") + " Year: " +  splitCCDateSelectElement("cc_expiry_year",formElmObj.fieldName,"year");
								// "cc_expiry_month" + i is passed in case there are may be multiple date fields used
								break;
			
			case "date" 	: 	// render hidden field where segmented fields are concatenated	
								// parse default value
								if (formElmObj.defaultValue == "")
									formElmObj.defaultValue = "00-00-0000";
									
									if (formElmObj.defaultValue.indexOf("-") != -1) var defaultArray = formElmObj.defaultValue.split("-");
									if (formElmObj.defaultValue.indexOf("/") != -1) var defaultArray = formElmObj.defaultValue.split("/");
									if (formElmObj.defaultValue.indexOf(":") != -1) var defaultArray = formElmObj.defaultValue.split(":");
									
									var defaultDay = defaultArray[0]; var defaultMonth = defaultArray[1]; var defaultYear = defaultArray[2];  
								
								formStr="<input type=\"hidden\" name=\""+ formElmObj.fieldName +"\" value=\"" + formElmObj.defaultValue +"\">";
								// render segmeted fields and onchange events calling updateDate function, which updates hidden 'parent' element above
								formStr += splitDateSelectElement("dob_day"+formElmObj.fieldName, formElmObj.fieldName,"day",defaultDay) + "&nbsp" + splitDateSelectElement("month_day"+formElmObj.fieldName,formElmObj.fieldName,"month",defaultMonth) + "&nbsp;" + splitDateSelectElement("dob_year"+formElmObj.fieldName,formElmObj.fieldName,"year",defaultYear);
								// "cc_expiry_month" + i is passed in case there are may be multiple date fields used
								break;
			
			case "submit"	:	// write submite button - default value is rendered into button text

								formStr="<input type=\"submit\" name=\""+ formElmObj.fieldName +"\" value=\""+formElmObj.defaultValue+"\" class=\"button\">";
								break;
			case "subheading":  	formStr="";
								break;
			case "calculated":  formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"text\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\" readonly/>"; 
								break;
			case "hidden":  	formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"hidden\" value=\""+formElmObj.defaultValue+"\"/>"; 
								break;
			case "text-area":  formStr="<textarea rows=\"5\" name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\">" + formElmObj.defaultValue+ "</textarea>"; 
								break;
			case "checkbox":  formStr="<input type=\"checkbox\" name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.maxValue+"\"  onClick=\""+formElmObj.onChangeAction+"\" "+ formElmObj.defaultValue +"/>"; 
								break;
								
			case "radio":  		for (var k=0; k<formElmObj.valueArray.length;k+=2)
								{
									formStr += "<div class=\"radioname\">"+formElmObj.valueArray[k+1]+"</div>";
									if (formElmObj.defaultValue == formElmObj.valueArray[k])
										formStr += "<div class=\"radiofield\"><input type=\"radio\" name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\" CHECKED/></div>";
											else
												formStr += "<div class=\"radiofield\"><input type=\"radio\" name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\"/></div>";
								}
								break;
			case "quiz" 	:	formStr= getQuizElements(fields[i]);
		}
		
		if (fieldOnly == "true") 
		{
			// only write the element itself
			document.write(formStr);
			return true; // do no more 
		}
		
		// form element string now built, last of all render element and name into DIVs within the page
		if (formElmObj.errorMsg) requiredString = "*"; // append asterix if this is a required field
		
		if (formElmObj.typeRequired == "checkbox")
		{
				document.write("<div class=\"formRow\">");
				document.write("<div class=\"checkboxright\">" + formStr + "</div>");
				document.write("<div class=\"checkboxleft\">" + formElmObj.friendlyName + requiredString + "</div>");
				document.write("</div>");
		}
		else if (formElmObj.typeRequired == "quiz")
		{	
			document.write("<div class=\"formRow QuizRow\">"); 
			// quiz question
			document.write("<div class=\"quizheader\">" + formElmObj.friendlyName + "</div>");
			// options
			document.write( formStr + "</div>");
		}
		else if (formElmObj.typeRequired == "submit")
		{	// button
			// write left and right aligned text field pairs
			document.write("<div class=\"formRow submitRow\">" + formStr + "</div>");
		}
		else
		{
			document.write("<div class=\"formRow\">"); 
			if (formStr != "") 
			{
				// write left and right aligned text field pairs
				formStr = "<div class=\"formleft\">" + formStr + "</div>";
				document.write("<div class=\"textleft\">" + formElmObj.friendlyName + requiredString + "</div>" + formStr );
				document.write("</div>");
			}
			else
			{	// write signle strap line
				document.write("<div class=\"subheading\">" + formElmObj.friendlyName + "</div></div>");
			}
		}
}

function getQuizElements(fieldObj)
{
	var optionString = ""; 
	var selString ="";
	var ctr=0;
	var selectedValue = fieldObj.defaultValue;
	if (fieldObj.defaultValue == "") selectedValue = -1;
	
	if (bDebug) alert ("Allow multiple for " + fieldObj.fieldName + "? : " + fieldObj.allowMultiple);
	var hiddenDefault="";
	
	// hidden element
	if (selectedValue != "-1") hiddenDefault = fieldObj.valueArray[(selectedValue * 2)];
	if (hiddenDefault == "undefined") hiddenDefault = ""; // ??
	//if (bDebug) optionString += "<input type=\"text\" name=\""+ fieldObj.fieldName +"\"value=\""+ hiddenDefault + "\" style=\"width: 300px;\"/>\n";
		//else 
		optionString += "<input type=\"hidden\" name=\""+ fieldObj.fieldName +"\" value=\""+ hiddenDefault + "\"/>\n";

	for (var i=0; i<fieldObj.valueArray.length; i+=2)
	{
		if (ctr == selectedValue) 
		{
			selString = " CHECKED";
		}
		else selString = "";  // default value of select
		ctr++;
		optionString += "<div class=\"quizoption\">\n";
		optionString += "<div class=\"quizright\">" + "<input type=\"checkbox\" name=\""+ fieldObj.fieldName + "_" + ctr +"\" value=\""+ fieldObj.valueArray[i] + "\"" + selString + " onClick=\"updateHiddenQuizField('"+fieldObj.fieldName+"','"+ "_" + ctr+ "','"+ (fieldObj.valueArray.length / 2)+"','"+fieldObj.allowMultiple+"')\"></div>\n";
		optionString += "<div class=\"quizleft\">" + fieldObj.valueArray[i+1] + "</div>\n";
		optionString += "</div>\n"; // quizoption
	}
	// alert ("151 Adding " + optionString);
	return optionString;

}

function updateHiddenQuizField(a,b,numberOfFields,allowMultiple)
{	// copies b into hidden field a 
//	if (bDebug) 
	if (bDebug) alert ("Update call a=" + a + " b=" + b  + "Fields : " + numberOfFields + " allow multiple " + allowMultiple)
	
	if (allowMultiple == "false")
	{	// selections must be unique
		document.form1.elements[a].value = document.form1.elements[a+b].value;
	
		for (var j=1; j<=numberOfFields; j++)
		{
			// alert ("value " + j + "(" + (a + j) + ") =" + document.form1.elements[(a + j)].value);
			
			if ("_" + j ==  b) 
			{
				if (document.form1.elements[(a + "_" + j)].checked) 
				{	// reversed because click checks box
					document.form1.elements[(a + "_" + j)].checked = true;
				}
				else
				{
					document.form1.elements[(a + "_" + j)].checked = false;
					// clear parent element
					document.form1.elements[a].value = "";
				}
			}
			else
			{
				// alert ("unchecking elements[" + (a + "_" + j) + "]");
				document.form1.elements[(a + "_" + j)].checked = false;	
			}
		}
	}
	else
	{	// selections can be multiple 
		var valueString = "";
		for (var j=1; j<=numberOfFields; j++)
		{	// concatenate value string from selected fields
			if (bDebug) alert ("element " + (a + "_" + j) + "checked? "  + document.form1.elements[(a + j)].checked);
			if (document.form1.elements[(a + "_" + j)].checked)
			{
				if (bDebug) alert ("Adding: " + document.form1.elements[(a + "_" + j)].value );
				valueString += document.form1.elements[(a + "_" + j)].value + " "; 
			}
		}
		if (bDebug) alert ("valuestring= " + valueString);
		document.form1.elements[a].value = valueString;
	}

}



function selectOption(valueArray,selectedValue)
{	// construct a string of option html elements corrpesponding to value and text pair array valueArray
	// selectedValue contains the index of the default element
	
	var optionString = ""; 
	var selString ="";
	var ctr=0;
		
	for (var i=0; i<valueArray.length; i+=2)
	{
			if (valueArray[i] == selectedValue) 
			{
				selString = "selected";
			}
			else selString = "";  // default value of select
			ctr++;
			
			optionString += "<option value=\""+ valueArray[i] + "\"" + selString + ">" + valueArray[i+1]+ "</option>\n";
	}
	
	return optionString;
}

function splitCCDateSelectElement(elName,elParent,type)
{	// generate month or year select box using current year as the base value
	 // type is month or year
	 // parent is the hidden element to be updated on change of this element 
	  var start = 1;  var end=1;
	  var now = new Date();
	   
	  if (type == "year") { start = now.getYear();  end = start + 5 }  // parameters of year loop
	  if (type == "month") { start = 1;  end = 12 }  // parameters of month loop
	  
	  var elString = "<select name=\""+ elName +"\" onchange=\"updateDate('" + elName + "','" + elParent + "','" + type + "')\">";
	  elString +=  "<option value=\"\"></option>\n"; // initial blank value
	  for (var i = start; i<end+1; i++)
	       elString +=  "<option value=\"" + i + "\">"+ i + "</option>\n";
            
      elString += "</select>";
	  return elString;
}

function splitDateSelectElement(elName,elParent,type,defaultValue)
{	// generate month or year select box using current year as the base value
	 // type is month or year
	 // parent is the hidden element to be updated on change of this element 
	  var start = 1;  var end=1;
	  var now = new Date();
	  
	  if (type == "day") { start = 1;  end = 31; }  
	  if (type == "year") { start = 1932;  end = 2006; }  // parameters of year loop
	  if (type == "month") { start = 1;  end = 12 }  // parameters of month loop
	  
	  var elString = "<select name=\""+ elName +"\" onchange=\"updateDate('" + elName + "','" + elParent + "','" + type + "')\">";
	  elString +=  "<option value=\"\"></option>\n"; // initial blank value
	  for (var i = start; i<end+1; i++)
	  {
		  if (i == defaultValue) 
		  elString +=  "<option value=\"" + i + "\" SELECTED>"+ i + "</option>\n";
		  	else
		  		elString +=  "<option value=\"" + i + "\">"+ i + "</option>\n";
	  }
      elString += "</select>";
	  return elString;
}

// update hidden date field on change of a day / month / year parameter
function updateDate(elName,elParent,type)
{	// this function is called onChange of segmented date fields
	// it updates the value of the element's parent hidden field used for data and validation
	 
	var hiddenField = document.form1.elements[elParent].value; // ", default value=" + selectedValue);
	var valueField = document.form1.elements[elName].value; // ", default value=" + selectedValue);
	if (bDebug) alert ("Date field changed is " + elName + " (type=" + type + ") value=" + valueField + "\nparent hidden element is " + elParent + " value=" + hiddenField);
	
	// initially hiddenField is 00-00-0000
	var splitField = hiddenField.split("-");
	// construct new date from changed field value
	switch (type) 
	{
		case "day"		:	hiddenField= valueField + "-" + splitField[1] + "-" + splitField[2]; break; // not currently used
		case "month"	: 	hiddenField= splitField[0] + "-" + valueField + "-" + splitField[2]; break;
		case "year"		: 	hiddenField= splitField[0] + "-" + splitField[1] + "-" + valueField; break;
	}
	// update hidden field
	document.form1.elements[elParent].value = hiddenField; 
	if (bDebug) alert ("Date field changed to " + hiddenField);
}


// define formElement class which holds all field and validation data
function formElementObj(fieldName,friendlyName,typeRequired,defaultValue,minValue,maxValue,errorMsg,className,valueArray,onChangeAction)
{
	this.fieldName = fieldName;				// name of field on form
	this.friendlyName = friendlyName;		// name of field for error messages
	this.typeRequired = typeRequired;		// type of field or value required
	this.defaultValue = defaultValue;		// default value of form field
	this.minValue = minValue;				// min value or length, depenmding on type
	this.maxValue = maxValue;				// max value or length, ...
	this.errorMsg = errorMsg;				// error message for a null or empty field
	this.validate = formElementValidate;	// validate function called on form submission
	this.className = className; 			// class applied to form element
	this.valueArray = valueArray;			// value array for multi-value elements, eg select or radio button arrays
	this.onChangeAction	= onChangeAction;
	
	//if (typeRequired == "checkbox") alert ("Maxvalue for " + fieldName  + " is " + maxValue);
}

function formElementValidate(formObj)
{	// direct validation to correct validation function for given 'data' type
	// this would be more elegant using polymorphic methods, maybe inr JS 2.0...?
	// but for now we have separate functions to validate string, select, email, cc expiry date and cc number elements 	

	if (!this.errorMsg) return true; // do not validate fields that are not required
	
	switch (this.typeRequired)
	{
		case "string" 	: return validateString(formObj,this);
		case "password" : return validateString(formObj,this);
		case "file" 	: return validateString(formObj,this);
		case "select" 	: return validateSelect(formObj,this);
		case "email" 	: return validateEmail(formObj,this);
		case "ccdate" 	: return validateDate(formObj,this);
		case "ccnumber" : return validateCCNumber(formObj,this);
		case "numeric"  : return validateNumber(formObj,this);
		case "hidden"   : return true; // validateNumber(formObj,this);
		case "text-area": return validateString(formObj,this); 
		case "checkbox"	: return validateCheckbox(formObj,this); 
		case "button"	: return true;
		case "submit"	: return true;
		case "quiz"		: return validateQuiz(formObj,this); 
	}
	// type not known 
	alert ("Error - form type " + this.typeRequired + " not recognised for " + this.fieldName);
	return false;
}

// validate string element
function validateString(formObj,fmElement)
{	// validate contents of a string field
	// field must be between min and max length
	
	var fieldValue = formObj[fmElement.fieldName].value;
	//if (bDebug) alert ("Validating " + fmElement.fieldName + " which has value " + fieldValue);
	if (fieldValue == "") 
	{
		alert(fmElement.errorMsg); return false;
	}
	if (fieldValue.length < fmElement.minValue) 
	{	
		alert("Error - minimum length for " + fmElement.friendlyName + " is " + fmElement.minValue + " characters");
		return false;
	}
	
	if (fieldValue.length > fmElement.maxValue) 
	{	
		alert("Error - maximum length for " + fmElement.friendlyName + " is " + fmElement.maxValue + " characters");
		return false;
	}

	return true;
}


function validateNumber(formObj,fmElement)
{	// number validation - not used on current form

	var fieldValue = formObj[fmElement.fieldName].value;
	if (fieldValue == "") 
	{
		alert(fmElement.errorMsg); return false;
	}
	
	if (fieldValue < fmElement.minValue) 
	{	
		alert("Error - minimum value for " + fmElement.friendlyName + " is " + fmElement.minValue);
		return false;
	}
	
	if (fieldValue > this.maxValue) 
	{	
		alert("Error - maximum value for " + fmElement.friendlyName + " is " + fmElement.maxValue);
		return false;
	}
	return true;
}

function validateCheckbox(formObj,fmElement)
{	// validate select box contents by checking the selectedIndex is between min and max values
	var fieldValue = formObj[fmElement.fieldName].checked;
	
	if (fieldValue.toString ==  fmElement.minValue) 
	{	
		alert(fmElement.errorMsg); 
		return false;
	}
	return true;
}


function validateSelect(formObj,fmElement)
{	// validate select box contents by checking the selectedIndex is between min and max values
	var fieldValue = formObj[fmElement.fieldName].selectedIndex;
	
	if (fieldValue < fmElement.minValue || fieldValue > fmElement.maxValue) 
	{	
		alert(fmElement.errorMsg); 
		return false;
	}
	return true;
}

function validateEmail(formObj,fmElement)
{	// validate email field using a regexp test
	
	var fieldValue = formObj[fmElement.fieldName].value;
	if (fieldValue == "") { alert(fmElement.errorMsg); return false; }
	// use regular expression to test for email validity
	var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ 
	if (!re.test(fieldValue)) 
	{
		alert("Error - " + fmElement.friendlyName + " appears to be invalid."); return false;
	}
	return true;
}

function isEmail(fieldValue)
{
	var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ 
	if (re.test(fieldValue)) return true
		else return false;
}

function validateDate(formObj,fmElement)
{	// validate CC Date - month and year must be in the future
	var fieldValue = formObj[fmElement.fieldName].value;
	var dateFields = fieldValue.split("-");
	var now = new Date;
	// getMonth is 0-11 i.e. month value -1
	if (parseInt(dateFields[2]) < now.getYear() || (dateFields[2] == now.getYear() && dateFields[1] < (parseInt(now.getMonth())+1)))
	{
		alert(fmElement.errorMsg); return false;
	}

	return true;
}

function validateCCNumber(formObj,fmElement)
{	// validate credit card number
	// this script does not macth a given number prefix with the CCnumber type and number length etc
	// this would be needed for a more watertight check
	
	var fieldValue = formObj[fmElement.fieldName].value;
	if (fieldValue == "") { alert(fmElement.errorMsg); return false; }
	if (parseInt(fieldValue) == 0) { alert(fmElement.errorMsg); return false; }
	
	// remove spaces and non numeric characters
	var reg = /[^0-9]/g
	fieldValue = fieldValue.replace(reg,"");
	
	if (fieldValue == "") {	alert(fmElement.errorMsg); return false; }
	// detect whether debug entry
	if (fieldValue == "9999") return true;
	// perform mod10 checksum
	// for simplicity assume correct length is always 16, though this may vary
	
      var checkSum = 0;

      //  Add even digits in even length strings or odd digits in odd length strings
      for (loc=1-(fieldValue.length % 2); loc < fieldValue.length; loc+=2) 
	  {
		 var val = parseInt(fieldValue.substr(loc, 1));
		 if (bDebug) alert ("adding " + val);
		 checkSum += val;
      }

      // Add odd digits in even length strings and vice versa
	for (loc=fieldValue.length % 2; loc < fieldValue.length; loc+=2)  
	{
         	var val = parseInt(fieldValue.substr(loc, 1)) * 2;
			if (bDebug) alert ("adding " + val + "* 2");
			if (val < 10) checkSum += val;	
			else  checkSum += val - 9;
    }
	
	if (bDebug) alert ("Total checksum = " + checkSum);
	if (checkSum % 10 != 0) { alert("Error - " + fmElement.friendlyName + " appears to be invalid."); return false; } 
	return true;
}


function validate_form()
{	// form validation engine

	var formObj = document.form1;
	
	for (i=0;i<fields.length;i++) 
	{
		if (!fields[i].validate(formObj)) return false;	
	}
		return true
}

function displayRoundTotal(val)
{
	var total = Math.round(100*val)/100;
	var displayStr = total;
	// add extra zero to signle decimal
	if 	(total*10== parseInt(total*10))
		displayStr = total + "0";
	// add decimal places to integer
	if (total==parseInt(total))
		displayStr = total + ".00";
	return displayStr;
}

// define value-display pair arrays for select field elements
var countryArray = new Array ("","Please select...","Australia","Australia","Algeria","Algeria","American Samoa","American Samoa","Argentina","Argentina","Armenia","Armenia","Austria","Austria","Bahamas","Bahamas","Bahrain","Bahrain","Bangladesh","Bangladesh","Barbados","Barbados","Belarus","Belarus","Belgium","Belgium","Belize","Belize","Bermuda","Bermuda","Bolivia","Bolivia","Brazil","Brazil","Brunei Darussalam","Brunei Darussalam","Cambodia","Cambodia","Canada","Canada","Chile","Chile","China","China","Colombia","Colombia","Croatia","Croatia","Cuba","Cuba","Cyprus","Cyprus","Czech Republic","Czech Republic","Denmark","Denmark","Djibouti","Djibouti","Dominican Republic","Dominican Republic","East Timor","East Timor","Ecuador","Ecuador","Egypt","Egypt","El Salvador","El Salvador","Equatorial Guinea","Equatorial Guinea","Eritrea","Eritrea","Estonia","Estonia","Ethiopia","Ethiopia","Falkland Islands","Falkland Islands","Fiji","Fiji","Finland","Finland","France","France","French Guiana","French Guiana","Frenh Southern Territories","French Southern Territories","FYROM","FYROM","Gabon","Gabon","Gambia","Gambia","Georgia","Georgia","Germany","Germany","Ghana","Ghana","Gibraltar","Gibraltar","Greece","Greece","Greenland","Greenland","Grenada","Grenada","Guadeloupe","Guadeloupe","Guam","Guam","Guinea","Guinea","Guyana","Guyana","Haiti","Haiti","Holland","Holland","Honduras","Honduras","Hong Kong","Hong Kong","Hungary","Hungary","Iceland","Iceland","India","India","Indonesia","Indonesia","Iran","Iran","Iraq","Iraq","Ireland","Ireland","Israel","Israel","Italy","Italy","Jamaica","Jamaica","Japan","Japan","Jordan","Jordan","Kazakhstan","Kazakhstan","Kenya","Kenya","Kiribati","Kiribati","Korea","Korea","Kuwait","Kuwait","Latvia","Latvia","Lebanon","Lebanon","Lesotho","Lesotho","Liberia","Liberia","Libyan Arab Jamahiriya","Libyan Arab Jamahiriya","Liechtenstein","Liechtenstein","Lithuania","Lithuania","Luxembourg","Luxembourg","Madagascar","Madagascar","Malawi","Malawi","Malaysia","Malaysia","Maldives","Maldives","Mali","Mali","Malta","Malta","Marshall Islands","Marshall Islands","Martinique","Martinique","Mauritania","Mauritania","Mauritius","Mauritius","Mayotte","Mayotte","Mexico","Mexico","Micronesia","Micronesia","Middle East","Middle East","Moldova","Moldova","Monaco","Monaco","Mongolia","Mongolia","Montserrat","Montserrat","Morocco","Morocco","Myanmar","Myanmar","Namibia","Namibia","Nauru","Nauru","Nepal","Nepal","Netherlands Antilles","Netherlands Antilles","New Caledonia","New Caledonia","New Zealand","New Zealand","Nicaragua","Nicaragua","Niger","Niger","Nigeria","Nigeria","Niue","Niue","Norfolk Island","Norfolk Island","Northern Africa","Northern Africa","Northern Mariana Islands","Northern Mariana Islands","Norway","Norway","Oman","Oman","Pakistan","Pakistan","Palau","Palau","Panama","Panama","Papua New Guinea","Papua New Guinea","Paraguay","Paraguay","Peru","Peru","Philippines","Philippines","Pitcairn","Pitcairn","Poland","Poland","Portugal","Portugal","Puerto Rico","Puerto Rico","Qatar","Qatar","Reunion","Reunion","Romania","Romania","Russia","Russia","Russian Federation","Russian Federation","Rwanda","Rwanda","Saint Helena","Saint Helena","Saint Kitts and Nevis","Saint Kitts and Nevis","Saint Lucia","Saint Lucia","Saint Pierre and Miquelon","Saint Pierre and Miquelon","Saint Vincent Grenadines","Saint Vincent Grenadines","Samoa","Samoa","San Marino","San Marino","Saudi Arabia","Saudi Arabia","Scotland","Scotland","Senegal","Senegal","Seychelles","Seychelles","Sierra Leone","Sierra Leone","Singapore","Singapore","Slovakia","Slovakia","Slovenia","Slovenia","Solomon Islands","Solomon Islands","Somalia","Somalia","South Africa","South Africa","Spain","Spain","Sri Lanka","Sri Lanka","Sudan","Sudan","Suriname","Suriname","Swaziland","Swaziland","Sweden","Sweden","Switzerland","Switzerland","Syrian Arab Republic","Syrian Arab Republic","Taiwan","Taiwan","Tajikistan","Tajikistan","Tanzania","Tanzania","Thailand","Thailand","Togo","Togo","Tokelau","Tokelau","Tonga","Tonga","Trinidad and Tobago","Trinidad and Tobago","Tunisia","Tunisia","Turkey","Turkey","Turkmenistan","Turkmenistan","Tuvalu","Tuvalu","Uganda","Uganda","Ukraine","Ukraine","United Arab Emirates","United Arab Emirates","United Kingdom","United Kingdom","United States of America","United States of America","Uruguay","Uruguay","Vanuatu","Vanuatu","Vatican City State","Vatican City State","Venezuela","Venezuela","Vietnam","Vietnam","Virgin Islands (British)","Virgin Islands (British)","Virgin Islands (U.S.)","Virgin Islands (U.S.)","Zimbabwe","Zimbabwe");

