// Check for jQuery
if (typeof (jQuery) === 'undefined')
	alert("jQuery is required by avp.js!");


var AVPViewModel = function() {

	// Handy self reference to the AVP ViewModel for usage in functions, to prevent confusion with 'this'
	var _vm = this;

	// Internal variable to keep track of visibility state
	this._visible = true;
	this._user_country_code = "00"; // Is what we use for not detected / not selected

	// Variable to keep track of we're using 2-digit year or 4-digit year, default is false
	// Set this to true in your client AVP instance if you want users to have to enter the whole 19XX 
	this.fullYear = false;

	// INITIALIZE
	// Here begins the code that is executed by the calling page (initialize)
	// --------------------------------------------------------------------------------

	this.init = function(service_url) {

		_vm.service_url = service_url;

		// We hide the optional no-javascript filler first, so that it's gone as fast as possible.
		jQuery(".avpFullScreenCover").hide();

		_vm._verify_html();
		_vm._verify_configuration();
		_vm._check_if_user_previously_verified();
		_vm._add_wrapper_style();
		_vm._populate_country_select_box();
		_vm._update_country_data();
		_vm._assign_date_field_behaviour();
		_vm._assign_submit_button_behaviour();

		_vm._detect_country();

		if (_vm._visible == false) {
			// Ensure 'displayed' is never triggered once 'hidden' has been triggered.
			// This case might occur if the callback from the xd receiver is REALLY fast.
			return;
		} else {

			// Prevent scrolling while AVP is showing
			jQuery("body").css("overflow", "hidden");
			jQuery(_vm).trigger("displayed");
		}

	};

	this._update_country_data = function() {
		_vm._assign_date_field_responsibilities();
		var drinking_age = _vm._get_drinking_age();
		jQuery(".avpDrinkingAge").text(drinking_age);
		jQuery(".avpCountry").val(_vm._user_country_code);
		if (_vm._user_country_code != "00")
			jQuery(_vm).trigger("country_updated", _vm._user_country_code);
	};


	// Check that all required AVP HTML is present.
	this._verify_html = function() {

		if (jQuery(".avpWrapper").length != 1) {
			alert('AVP HTML is incorrect. AVP needs exactly one element with class "avpWrapper" to work.');
			return;
		}

		if (jQuery(".avpBirthDate span.avpYear input").length != 1 || jQuery(".avpBirthDate span.avpMonth input").length != 1 || jQuery(".avpBirthDate span.avpDay input").length != 1) {
			alert('AVP HTML is incorrect. Date elements are not correct.');
			return;
		}

		if (jQuery(".avpSubmit").length != 1) {
			alert('AVP HTML is incorrect. AVP needs exactly one element with class "avpSubmit" to work.');
			return;
		}
	};

	// Verifys that configuration parameters are set correctly
	this._verify_configuration = function() {

		if (_vm.service_url == null) {
			alert('Configuration variable "_avp.service_url" must be set to a valid absolute url to an lda_xd page before calling initialize!');
			return;
		}
	}

	this._check_if_user_previously_verified = function() {

		// Callback
		var on_user_is_previously_verified = function() {
			_vm._set_calling_domain_cookie();
			_vm._hide_avp();
		}

		// Check if there is a cookie on calling domain        
		if (readCookie("avp_accepted_caller") == "yes") {
			on_user_is_previously_verified();
		}

		// Check if there is a cookie on the mother domain using JSONP
		var url = _vm.service_url + "?command=get_cookie&callback=?";
		jQuery.getJSON(url, function(data) {
			if (data.avp_accepted_mother == "yes")
				on_user_is_previously_verified();
		});
	};



	this._add_wrapper_style = function() {

		$(".avpWrapper").css("top", "0");
		$(".avpWrapper").css("left", "0");
		$(".avpWrapper").css("width", "100%");
		$(".avpWrapper").css("height", "2500px");
		$(".avpWrapper").css("z-index", "1000");

		_vm._fit_wrapper_to_window();
		$(window).bind('resize', _vm._fit_wrapper_to_window);
	}

	this._fit_wrapper_to_window = function() {
		// We'd like to use "position: fixed", but IE has crappy support for that,
		// so we use a bit of JS instead:
		$(".avpWrapper").css("position", "absolute");
		var contentHeight = $("html").height();
		if (contentHeight != 0 && contentHeight != null)
			$(".avpWrapper").css("height", contentHeight + "px");

	}

	this._assign_date_field_responsibilities = function() {
		// Date field responsibility assignment (year/month/day)
		// We do this by assigning them classes in the format "avpYear", "avpMonth", "avpDay".        
		var dateOrder = null;

		jQuery(DATE_FORMATS).each(function(index, dateFormat) {
			jQuery(dateFormat.countryCodes).each(function(index, countryCode) {
				if (countryCode == _vm._user_country_code)
					dateOrder = dateFormat.order;
			});
		});
		if (dateOrder == null)
			dateOrder = defaultDateOrder = ["Year", "Month", "Day"];

		jQuery(".avpBirthDate input")
            .removeClass("avpBirthDatePartLeft")
            .removeClass("avpBirthDatePartMiddle")
            .removeClass("avpBirthDatePartRight");

		// Shove the input elements around in the correct order.
		jQuery(dateOrder).each(function(index, datePart) {
			var selector = ".avp" + datePart;
			// Detach and replace it in it's new correct position
			jQuery(selector).detach().appendTo(".avpBirthDate");
		});


		jQuery(".avpBirthDate input").each(function(index, item) {
			// Transfer the value attribute the the _dafaultValue data of the element.
			// _defaultValue is used by jumpy() to prevent accidental tabbing.
			jQuery(this).data("_defaultValue", jQuery(this).val());
		});


		jQuery(".avpBirthDate input:first").select();
	}

	this._assign_date_field_behaviour = function() {
		jQuery(".avpBirthDate input").attr("maxlength", "2");
		jQuery(".avpBirthDate input").attr("size", "2");
		jQuery(".avpBirthDate input").jumpy();

		// If we are using 4-digit years, change behavior somewhat
		if (this.fullYear) {
			jQuery(".avpYear input").attr("maxlength", "4");
			jQuery(".avpYear input").attr("size", "4");
			jQuery(".avpYear input").val("YYYY");
		}

		jQuery(".avpBirthDate input").click(function() {
			this.select();
			return false;
		});

		jQuery(".avpBirthDate input").unbind("keypress");
		jQuery(".avpBirthDate input").keypress(function(e) {
			var enterKey = 13;
			if (e.which == enterKey) {
				_vm._verify_age();
				return false;
			}
		});
	}

	this._populate_country_select_box = function() {
		if (jQuery('.avpCountry').length == 0)
			return;

		var optionsHtml = "";
		jQuery(COUNTRIES).each(function(index, country) {
			optionsHtml += '<option value="' + country.code + '">' + country.name + "</option>";
		});
		jQuery('.avpCountry').html(optionsHtml);

		jQuery('.avpCountry').change(function() {
			_vm._user_country_code = jQuery('.avpCountry').val();
			_vm._update_country_data();
			return false;
		});
	}

	this._assign_submit_button_behaviour = function() {
		jQuery(".avpSubmit").click(function() {
			_vm._verify_age();
			return false;
		});
	};

	this._detect_country = function() {
		var url = _vm.service_url + "?command=get_country_code&callback=?";
		jQuery.getJSON(url, function(data) {
			_vm._user_country_code = data.country_code.toUpperCase();
			if (_vm._user_country_code == "")
				_vm._user_country_code = "00";
			_vm._update_country_data();
		});
	};

	// VERIFY AGE
	// Here begins the code that executes when the submit button is pressed.
	// --------------------------------------------------------------------------------

	this._verify_age = function() {

		// Require user to select their country
		// if there is a country selector on the AVP.
		if (_vm._user_country_code == "00")
			if (jQuery(".ldaCountry").length == 1)
			alert("Please select your country!");


		try {
			var enteredDate = _vm._parse_entered_date();
		}
		catch (Error) {
			jQuery(this).trigger("invalid_date");
			return;
		}

		var drinking_age_in_user_country = _vm._get_drinking_age();

		if (drinking_age_in_user_country == 99) {
			jQuery(_vm).trigger("drinking_banned");

		} else {

			// Is she old enough?

			var now = new Date();
			var birth_date_of_person_with_legal_drinking_age = new Date((now.getFullYear() - drinking_age_in_user_country), now.getMonth(), now.getDate(), 0, 0, 0);
			var isOldEnough = enteredDate < birth_date_of_person_with_legal_drinking_age;
			if (isOldEnough) {

				// Entered date is an acceptable age!
				_vm._set_calling_domain_cookie();
				_vm._set_mother_domain_cookie();
				_vm._check_for_redirect();
				_vm._hide_avp();

			} else {
				jQuery(_vm).trigger("too_young");
			}
		}
	}

	this._parse_entered_date = function() {
		try {
			var year = parseInt(jQuery(".avpYear input").val(), 10);
			var month = parseInt(jQuery(".avpMonth input").val(), 10);
			var day = parseInt(jQuery(".avpDay input").val(), 10);

			// If we are using 4-digit years, do this, else do that
			if (this.fullYear) {
				isValidDate = !isNaN(year) && year != 0 && year > 999 &&
				!isNaN(month) && month != 0 && month <= 12
				!isNaN(day) && day != 0 && day <= 31;
			} else {
				isValidDate = !isNaN(year) && year != 0 &&
				!isNaN(month) && month != 0 && month <= 12
				!isNaN(day) && day != 0 && day <= 31;
			}

			// If we are using 4-digit years, do this, else do that
			if (isValidDate) {
				if (this.fullYear)
					return new Date(year, month, day);
				else
					return new Date(1900 + year, month, day);
			}
		}
		catch (err) { }
		throw "Invalid date!";
	}



	this._get_drinking_age = function() {
		var user_country_code;

		var found_age = null;

		jQuery(DRINKING_AGE_RANGES).each(function(index, ageRange) {
			if (found_age != null) return;
			jQuery(ageRange.countryCodes).each(function(index, countryCode) {
				if (found_age != null) return;
				if (countryCode == _vm._user_country_code)
					found_age = parseInt(ageRange.age);
			});
		});
		if (found_age) return found_age;
		return 18; // Fallback age
	}



	this._set_calling_domain_cookie = function() {

		// We want so set a calling cookie ("calling" refers to the domain calling the LDA)
		// so that we don't have to go to the mother domain on every request.

		// If not already set, write LDAAccepted session cookie on calling Domain:s

		if (readCookie("avp_accepted_caller") == null) {
			document.cookie = "avp_accepted_caller=yes";
			// We only write a session cookie, not a persistent one, in part because we don't know for
			// how long the cookie should live, and in part because it would mess with CDN caching.
		}
	}

	this._set_mother_domain_cookie = function() {

		// 'Mother domain' refers to the domain hosting the AVP scripts.
		// This cookie is used if the user moves from one Absolut domain to another, such as
		// between absolut.com and absolutdrinks.com. It's also used to remember the users age
		// if the user has checked the "remember me" box.

		// The AVP implementation might not care about cross-domain identification, so it's optional.
		if (_vm.service_url == null)
			return;

		var url = _vm.service_url + "?command=set_cookie";

		if (jQuery(".avpRemember").is(':checked'))
			url = url + "&remember=yes";

		// Open the xd receiver in a new window and then immideately unfocus it.
		// And no, smartarse, Iframing won't work because of third-party cookie restrictions
		// in some browsers.	

		var oPopUnder = window.open(url, "avp_service", "location=0,status=0,scrollbars=0,width=50,height=50");
		oPopUnder.blur();
		window.focus();

		var closepopuptimeout = 2000;
		// The XD closes itself after setting the mother domain cookie, but
		// in case there is a failure, we don't want the popup hanging around.
		setTimeout(function() { try { oPopUnder.close(); } catch (err) { } }, closepopuptimeout);
	}

	this._check_for_redirect = function() {
		// Check redirect list if we should redirect to somewhere else
		// once the avp is passed
		var url = _vm.service_url + "?command=get_redirect&cc=" + _vm._user_country_code + "&callback=?";
		jQuery.getJSON(url, function(data) {
			if (data.redirect.length > 0) {
				self.location = data.redirect;
			}
		});
	}

	this._hide_avp = function() {
		$("body").css("overflow", "auto");
		_vm._visible = false;
		jQuery(".avpWrapper").hide();
		jQuery(_vm).trigger("hidden");
		this._check_for_redirect();
	}
};



// BEGIN CONSTANTS
// -------------------------------------------------------------------------------
// These could theoretically be retrieved by calls to a JSON-style webservice on the 
// mother domain on the future, but for now, they do fine as hard-coded.

var DRINKING_AGE_RANGES = [
	{ age: 21, countryCodes: ["FI", "IS", "NO", "PY", "TH", "US", "MY"] },
	{ age: 19, countryCodes: ["CA", "NI", "KR"] },
	{ age: 20, countryCodes: ["SE", "JP"] },
	{ age: 22, countryCodes: ["BH", "BY", "EG", "ID", "KW", "MN", "NG", "OM", "WS", "AE"] },
	{ age: 25, countryCodes: ["IN"] },
	{ age: 99, countryCodes: ["AF", "BD", "BN", "IR", "IQ", "JO", "LY", "UZ", "PK", "SA", "TN", "YE", "SU"] }
];


var DATE_FORMATS = [
    { order: ["Month", "Day", "Year"], countryCodes: ["US"] },
    { order: ["Year", "Month", "Day"], countryCodes: ["SE", "KR", "CN", "CA", "JP", "LV", "LT", "MN", "PL"] }
];

var REDIRECT_LIST = [{}];

var COUNTRIES = [
	{ code: "00", name: "Select country" },
	{ code: "AF", name: "Afghanistan" },
	{ code: "AL", name: "Albania" },
	{ code: "DZ", name: "Algeria" },
	{ code: "AS", name: "American Samoa" },
	{ code: "AD", name: "Andorra" },
	{ code: "AO", name: "Angola" },
	{ code: "AI", name: "Anguilla" },
	{ code: "AQ", name: "Antarctica" },
	{ code: "AG", name: "Antigua &amp; Barbuda" },
	{ code: "AR", name: "Argentina" },
	{ code: "AM", name: "Armenia" },
	{ code: "AW", name: "Aruba" },
	{ code: "AU", name: "Australia" },
	{ code: "AT", name: "Austria" },
	{ code: "AZ", name: "Azerbaijan" },
	{ code: "BS", name: "Bahamas" },
	{ code: "BH", name: "Bahrain" },
	{ code: "BD", name: "Bangladesh" },
	{ code: "BB", name: "Barbados" },
	{ code: "BY", name: "Belarus" },
	{ code: "BE", name: "Belgium" },
	{ code: "BZ", name: "Belize" },
	{ code: "BJ", name: "Benin" },
	{ code: "BM", name: "Bermuda" },
	{ code: "BT", name: "Bhutan" },
	{ code: "BO", name: "Bolivia" },
	{ code: "BA", name: "Bosnia &amp; Herzeg..." },
	{ code: "BW", name: "Botswana" },
	{ code: "BV", name: "Bouvet Island" },
	{ code: "BR", name: "Brazil" },
	{ code: "IO", name: "British Indian Ocean" },
	{ code: "BN", name: "Brunei Darussalam" },
	{ code: "BG", name: "Bulgaria" },
	{ code: "BF", name: "Burkina Faso" },
	{ code: "BI", name: "Burundi" },
	{ code: "KH", name: "Cambodia" },
	{ code: "CM", name: "Cameroon" },
	{ code: "CA", name: "Canada" },
	{ code: "CV", name: "Cape Verde" },
	{ code: "KY", name: "Cayman Islands" },
	{ code: "CF", name: "Central African Rep." },
	{ code: "TD", name: "Chad" },
	{ code: "CL", name: "Chile" },
	{ code: "CN", name: "China" },
	{ code: "CX", name: "Christmas Island" },
	{ code: "CC", name: "Cocos (Keeling) Isl." },
	{ code: "CO", name: "Colombia" },
	{ code: "KM", name: "Comoros" },
	{ code: "CG", name: "Congo" },
	{ code: "CK", name: "Cook Islands" },
	{ code: "CR", name: "Costa Rica" },
	{ code: "CI", name: "Cote D'Ivoire" },
	{ code: "HR", name: "Croatia (Hrvatska)" },
	{ code: "CU", name: "Cuba" },
	{ code: "CY", name: "Cyprus" },
	{ code: "CZ", name: "Czech Republic" },
	{ code: "DK", name: "Denmark" },
	{ code: "DJ", name: "Djibouti" },
	{ code: "DM", name: "Dominica" },
	{ code: "DO", name: "Dominican Rep." },
	{ code: "TP", name: "East Timor" },
	{ code: "EC", name: "Ecuador" },
	{ code: "EG", name: "Egypt" },
	{ code: "SV", name: "El Salvador" },
	{ code: "GQ", name: "Equatorial Guinea" },
	{ code: "ER", name: "Eritrea" },
	{ code: "EE", name: "Estonia" },
	{ code: "ET", name: "Ethiopia" },
	{ code: "FK", name: "Falkland Islands" },
	{ code: "FO", name: "Faroe Islands" },
	{ code: "FJ", name: "Fiji" },
	{ code: "FI", name: "Finland" },
	{ code: "FR", name: "France" },
	{ code: "FX", name: "France, Metropolitan" },
	{ code: "GF", name: "French Guiana" },
	{ code: "PF", name: "French Polynesia" },
	{ code: "TF", name: "French Southern terr." },
	{ code: "GA", name: "Gabon" },
	{ code: "GM", name: "Gambia" },
	{ code: "GE", name: "Georgia" },
	{ code: "DE", name: "Germany" },
	{ code: "GH", name: "Ghana" },
	{ code: "GI", name: "Gibraltar" },
	{ code: "GR", name: "Greece" },
	{ code: "GL", name: "Greenland" },
	{ code: "GD", name: "Grenada" },
	{ code: "GP", name: "Guadeloupe" },
	{ code: "GU", name: "Guam" },
	{ code: "GT", name: "Guatemala" },
	{ code: "GN", name: "Guinea" },
	{ code: "GW", name: "Guinea-Bissau" },
	{ code: "GY", name: "Guyana" },
	{ code: "HT", name: "Haiti" },
	{ code: "HM", name: "Heard &amp; Mc Donalds" },
	{ code: "HN", name: "Honduras" },
	{ code: "HK", name: "Hong Kong" },
	{ code: "HU", name: "Hungary" },
	{ code: "IS", name: "Iceland" },
	{ code: "IN", name: "India" },
	{ code: "ID", name: "Indonesia" },
	{ code: "IR", name: "Iran" },
	{ code: "IQ", name: "Iraq" },
	{ code: "IE", name: "Ireland" },
	{ code: "IL", name: "Israel" },
	{ code: "IT", name: "Italy" },
	{ code: "JM", name: "Jamaica" },
	{ code: "JP", name: "Japan" },
	{ code: "JO", name: "Jordan" },
	{ code: "KZ", name: "Kazakhstan" },
	{ code: "KE", name: "Kenya" },
	{ code: "KI", name: "Kiribati" },
	{ code: "KP", name: "Korea" },
	{ code: "KR", name: "Korea, Republic of" },
	{ code: "KW", name: "Kuwait" },
	{ code: "KG", name: "Kyrgyzstan" },
	{ code: "LA", name: "Lao" },
	{ code: "LV", name: "Latvia" },
	{ code: "LB", name: "Lebanon" },
	{ code: "LS", name: "Lesotho" },
	{ code: "LR", name: "Liberia" },
	{ code: "LY", name: "Libyan Arab Jamahiriya" },
	{ code: "LI", name: "Liechtenstein" },
	{ code: "LT", name: "Lithuania" },
	{ code: "LU", name: "Luxembourg" },
	{ code: "MO", name: "Macau" },
	{ code: "MK", name: "Macedonia" },
	{ code: "MG", name: "Madagascar" },
	{ code: "MW", name: "Malawi" },
	{ code: "MY", name: "Malaysia" },
	{ code: "MV", name: "Maldives" },
	{ code: "ML", name: "Mali" },
	{ code: "MT", name: "Malta" },
	{ code: "MH", name: "Marshall Islands" },
	{ code: "MQ", name: "Martinique" },
	{ code: "MR", name: "Mauritania" },
	{ code: "MU", name: "Mauritius" },
	{ code: "YT", name: "Mayotte" },
	{ code: "MX", name: "Mexico" },
	{ code: "FM", name: "Micronesia" },
	{ code: "MD", name: "Moldova" },
	{ code: "MC", name: "Monaco" },
	{ code: "MN", name: "Mongolia" },
	{ code: "MS", name: "Montserrat" },
	{ code: "MA", name: "Morocco" },
	{ code: "MZ", name: "Mozambique" },
	{ code: "MM", name: "Myanmar" },
	{ code: "NA", name: "Namibia" },
	{ code: "NR", name: "Nauru" },
	{ code: "NP", name: "Nepal" },
	{ code: "NL", name: "Netherlands" },
	{ code: "AN", name: "Netherlands Antilles" },
	{ code: "NC", name: "New Caledonia" },
	{ code: "NZ", name: "New Zealand" },
	{ code: "NI", name: "Nicaragua" },
	{ code: "NE", name: "Niger" },
	{ code: "NG", name: "Nigeria" },
	{ code: "NU", name: "Niue" },
	{ code: "NF", name: "Norfolk Island" },
	{ code: "MP", name: "Northern Mariana Islands" },
	{ code: "NO", name: "Norway" },
	{ code: "OM", name: "Oman" },
	{ code: "PK", name: "Pakistan" },
	{ code: "PW", name: "Palau" },
	{ code: "PA", name: "Panama" },
	{ code: "PG", name: "Papua New Guinea" },
	{ code: "PY", name: "Paraguay" },
	{ code: "PE", name: "Peru" },
	{ code: "PH", name: "Philippines" },
	{ code: "PN", name: "Pitcairn" },
	{ code: "PL", name: "Poland" },
	{ code: "PT", name: "Portugal" },
	{ code: "PR", name: "Puerto Rico" },
	{ code: "QA", name: "Qatar" },
	{ code: "RE", name: "Reunion" },
	{ code: "RO", name: "Romania" },
	{ code: "RU", name: "Russian Federation" },
	{ code: "RW", name: "Rwanda" },
	{ code: "KN", name: "Saint Kitts and Nevis" },
	{ code: "LC", name: "Saint Lucia" },
	{ code: "VC", name: "Saint Vincent &amp; Grenadines" },
	{ code: "WS", name: "Samoa" },
	{ code: "SM", name: "San Marino" },
	{ code: "ST", name: "Sao Tome and Principe" },
	{ code: "SA", name: "Saudi Arabia" },
	{ code: "SN", name: "Senegal" },
	{ code: "SC", name: "Seychelles" },
	{ code: "SL", name: "Sierra Leone" },
	{ code: "SG", name: "Singapore" },
	{ code: "SK", name: "Slovakia (Slovak Rep)" },
	{ code: "SI", name: "Slovenia" },
	{ code: "SB", name: "Solomon Islands" },
	{ code: "SO", name: "Somalia" },
	{ code: "ZA", name: "South Africa" },
	{ code: "ES", name: "Spain" },
	{ code: "LK", name: "Sri Lanka" },
	{ code: "SH", name: "St. Helena" },
	{ code: "PM", name: "St. Pierre and Miquelon" },
	{ code: "SD", name: "Sudan" },
	{ code: "SR", name: "Suriname" },
	{ code: "SJ", name: "Svalbard Jan Mayen" },
	{ code: "SZ", name: "Swaziland" },
	{ code: "SE", name: "Sweden" },
	{ code: "CH", name: "Switzerland" },
	{ code: "SY", name: "Syrian Arab Republic" },
	{ code: "TW", name: "Taiwan" },
	{ code: "TJ", name: "Tajikistan" },
	{ code: "TZ", name: "Tanzania" },
	{ code: "TH", name: "Thailand" },
	{ code: "TG", name: "Togo" },
	{ code: "TK", name: "Tokelau" },
	{ code: "TO", name: "Tonga" },
	{ code: "TT", name: "Trinidad and Tobago" },
	{ code: "TN", name: "Tunisia" },
	{ code: "TR", name: "Turkey" },
	{ code: "TM", name: "Turkmenistan" },
	{ code: "TC", name: "Turks &amp; Caicos Islands" },
	{ code: "TV", name: "Tuvalu" },
	{ code: "UG", name: "Uganda" },
	{ code: "UA", name: "Ukraine" },
	{ code: "AE", name: "United Arab Emirates" },
	{ code: "GB", name: "United Kingdom" },
	{ code: "US", name: "United States" },
	{ code: "UM", name: "United States Minor Islands" },
	{ code: "UY", name: "Uruguay" },
	{ code: "UZ", name: "Uzbekistan" },
	{ code: "VU", name: "Vanuatu" },
	{ code: "VA", name: "Vatican City State" },
	{ code: "VE", name: "Venezuela" },
	{ code: "VN", name: "Viet NAM" },
	{ code: "VG", name: "Virgin Islands (British)" },
	{ code: "VI", name: "Virgin Islands (U.S.)" },
	{ code: "WF", name: "Wallis &amp; Futuna Islands" },
	{ code: "EH", name: "Western Sahara" },
	{ code: "YE", name: "Yemen" },
	{ code: "YU", name: "Yugoslavia" },
	{ code: "ZR", name: "Zaire" },
	{ code: "ZM", name: "Zambia" },
	{ code: "ZW", name: "Zimbabwe" }
];













// BEGIN AVP UTILITY FUNCTIONS
// --------------------------------------------------------------------------------
// These are backing functions for the AVP, and not so much part of the main logic.


// Reads the value of a cookie
function readCookie(b) { b = b + "="; for (var d = document.cookie.split(";"), c = 0; c < d.length; c++) { for (var a = d[c]; a.charAt(0) == " "; ) a = a.substring(1, a.length); if (a.indexOf(b) == 0) return a.substring(b.length, a.length) } return null };


/*
JUMPYFIELD is a simple little thing that makes the focus jump between fields when they reach maxlength.
Usage:

$(".myInputFields").jumpy();

jumpy also accepts an optional array of default values that count the fields as "empty". Example:
$(".myInputFields").jumpy(["YY","MM","DD"]);
*/
jQuery.fn.jumpy = function() {

    // Save the context in the element so that we know which fields to jump between.
    this.data("_jumpySelector", this.selector);

    this.keyup(function(event) {

        var tabKeyCode = 9;
        if (event.keyCode == tabKeyCode) {
            // Ignore accidental tabbing as a result of the user not knowing about the
            // jumpy fields, and trying to tab after filling out a field.
            var previousJumpy = jQuery(this)._getPreviousJumpyField();

            var isEmpty = jQuery(previousJumpy).val().length == 0;
            var hasDefaultValue = jQuery(previousJumpy).data("_defaultValue") == jQuery(previousJumpy).val();
            if (isEmpty || hasDefaultValue) 
                previousJumpy.focus().select();   
            
            return false;
        }
        if (jQuery(this).val().length >= parseInt(jQuery(this).attr("maxlength"))) {
            var nextjf = jQuery(this)._getSubsequentJumpyField();
            jQuery(nextjf).focus().select();

        }
    });
};

jQuery.fn._getSubsequentJumpyField = function() {
    var lastIterated = null;
    var subsequent = null;
    var originator = this[0];

    var selector = jQuery(this).data("_jumpySelector");
    jQuery(selector).each(function(index, iterated) {
        if (subsequent == null) {
            if (lastIterated == originator) {
                subsequent = this;
            }
            lastIterated = this;
        }
    });
    return subsequent;
}

jQuery.fn._getPreviousJumpyField = function() {
    var lastIterated = null;
    var previous = null;
    var originator = this[0];

    var selector = jQuery(this).data("_jumpySelector");
    jQuery(selector).each(function(index, iterated) {
        if (previous == null) {
            if (this == originator) {
                previous = lastIterated;
            }
            lastIterated = this;
        }
    });

    return previous;
}



var _avp = new AVPViewModel();
