
var AgeGate = function() {

	var
		Country,
		CountryCollection,
		_form,
		_countrySelect,
		_daySelect,
		_monthSelect,
		_yearSelect,
		_remember,
		_errorMessageElement;


	Country = function() {
		var
			_name,
			_iso,
			_minimumAge;


		this.create = function() {
			return new Country;
		};

		this.getName = function() {
			return _name;
		};

		this.getIso = function() {
			return _iso;
		};

		this.getMinimumAge = function() {
			return _minimumAge;
		}

		this.setIso = function( iso ) {
			_iso = iso;
			return this;
		};

		this.setName = function( name ) {
			_name = name;
			return this;
		};

		this.setMinimumAge = function( minimumAge ) {
			_minimumAge = minimumAge;
			return this;
		};

		this.createOption = function()
		{
			var option = document.createElement('option');
			option.text = this.getName();
			option.value = this.getIso();

			return option;			
		}

		this.isAllowed = function()
		{
			return ( typeof _minimumAge === 'number' ) && _minimumAge != 0;
		}

	}


	CountryCollection = function ()
	{
		var
			_countryArray = [];
			_countryIndexedByIso = {};

		this.addCountry = function( country ) {
			_countryArray[ _countryArray.length ] = country;
			_countryIndexedByIso[ country.getIso() ] = country;
		}

		this.getCountryForIso = function( iso ) {
			return _countryIndexedByIso[ iso ];
		}

		this.getCountryArray = function() {
			return _countryArray;
		}


		this.populate = function( data ) {

			for ( var i in data ) {
				this.addCountry( (new Country).setIso(data[i][0]).setName(data[i][1]).setMinimumAge(data[i][2]) );
			}
		}

	};


	var data =
[
  ["AF","Afghanistan",0],
  ["AL","Albania",18],
  ["DZ","Algeria",18],
  ["AD","Andorra",18],
  ["AO","Angola",18],
  ["AG","Antigua and Barbuda",18],
  ["AR","Argentina",18],
  ["AM","Armenia",18],
  ["AU","Australia",18],
  ["AT","Austria",18],
  ["AZ","Azerbaijan",18],
  ["BS","Bahamas",18],
  ["BH","Bahrain",21],
  ["BD","Bangladesh",0],
  ["BB","Barbados",18],
  ["BY","Belarus",21],
  ["BE","Belgium",18],
  ["BZ","Belize",18],
  ["BJ","Benin",18],
  ["BT","Bhutan",18],
  ["BO","Bolivia",18],
  ["BA","Bosnia and Herzegovina",18],
  ["BW","Botswana",18],
  ["BR","Brazil",18],
  ["BN","Brunei Darussalam",0],
  ["BG","Bulgaria",18],
  ["BF","Burkina Faso",18],
  ["KH","Cambodia",18],
  ["CM","Cameroon",18],
  ["CA","Canada",19],
  ["CV","Cape Verde",18],
  ["CF","Central African Republic",18],
  ["TD","Chad",18],
  ["CL","Chile",18],
  ["CN","China",18],
  ["CO","Colombia",18],
  ["CG","Congo",18],
  ["CR","Costa Rica",18],
  ["CI","Côte d'Ivoire",18],
  ["HR","Croatia",18],
  ["CU","Cuba",18],
  ["CY","Cyprus",18],
  ["CZ","Czech Republic",18],
  ["DK","Denmark",18],
  ["DJ","Djibouti",18],
  ["DM","Dominica",18],
  ["DO","Dominican Republic",18],
  ["EC","Ecuador",18],
  ["EG","Egypt",21],
  ["SV","El Salvador",18],
  ["GQ","Equatorial Guinea",18],
  ["EE","Estonia",18],
  ["FJ","Fiji",18],
  ["FI","Finland",0],
  ["FR","France",0],
  ["PF","French Polynesia",0],
  ["GA","Gabon",18],
  ["GM","Gambia",18],
  ["GE","Georgia",18],
  ["DE","Germany",18],
  ["GH","Ghana",18],
  ["GR","Greece",18],
  ["GD","Grenada",18],
  ["GT","Guatemala",18],
  ["GN","Guinea",18],
  ["GW","Guinea-Bissau",18],
  ["GY","Guyana",18],
  ["HT","Haiti",18],
  ["HN","Honduras",18],
  ["HK","Hong Kong",18],
  ["HU","Hungary",18],
  ["IS","Iceland",0],
  ["IN","India",25],
  ["ID","Indonesia",21],
  ["IR","Iran",0],
  ["IQ","Iraq",0],
  ["IE","Ireland",18],
  ["IL","Israel",18],
  ["IT","Italy",18],
  ["JM","Jamaica",18],
  ["JP","Japan",20],
  ["JO","Jordan",0],
  ["KZ","Kazakhstan",18],
  ["KE","Kenya",18],
  ["KW","Kuwait",21],
  ["KG","Kyrgyzstan",18],
  ["LA","Laos",18],
  ["LV","Latvia",18],
  ["LB","Lebanon",18],
  ["LS","Lesotho",18],
  ["LR","Liberia",18],
  ["LY","Libya",0],
  ["LI","Liechtenstein",18],
  ["LT","Lithuania",18],
  ["LU","Luxembourg",18],
  ["MK","Macedonia",18],
  ["MG","Madagascar",18],
  ["MW","Malawi",18],
  ["MY","Malaysia",18],
  ["MV","Maldives",18],
  ["ML","Mali",18],
  ["MT","Malta",18],
  ["MR","Mauritania",18],
  ["MU","Mauritius",18],
  ["MX","Mexico",18],
  ["FM","Micronesia",18],
  ["MD","Moldova",18],
  ["MC","Monaco",18],
  ["MN","Mongolia",21],
  ["MA","Morocco",18],
  ["MZ","Mozambique",18],
  ["NA","Namibia",18],
  ["NP","Nepal",0],
  ["NL","Netherlands",18],
  ["NZ","New Zealand",18],
  ["NI","Nicaragua",19],
  ["NE","Niger",18],
  ["NG","Nigeria",21],
  ["KP","North Korea",18],
  ["NO","Norway",0],
  ["OM","Oman",21],
  ["PK","Pakistan",0],
  ["PA","Panama",18],
  ["PG","Papua New Guinea",18],
  ["PY","Paraguay",20],
  ["PE","Peru",18],
  ["PH","Philippines",18],
  ["PL","Poland",0],
  ["PT","Portugal",18],
  ["QA","Qatar",18],
  ["RO","Romania",18],
  ["RU","Russia",18],
  ["RW","Rwanda",18],
  ["KN","Saint Kitts and Nevis",18],
  ["LC","Saint Lucia",18],
  ["VC","Saint Vincent and the Grenadines",18],
  ["WS","Samoa",21],
  ["SM","San Marino",18],
  ["ST","Sao Tome and Principe",18],
  ["SA","Saudi Arabia",0],
  ["SN","Senegal",18],
  ["RS","Serbia and Montenegro",18],
  ["SC","Seychelles",18],
  ["SL","Sierra Leone",18],
  ["SG","Singapore",18],
  ["SK","Slovakia",18],
  ["SL","Slovenia",18],
  ["SO","Somalia",18],
  ["ZA","South Africa",18],
  ["KR","South Korea",19],
  ["ES","Spain",18],
  ["LK","Sri Lanka",18],
  ["SD","Sudan",0],
  ["SR","Suriname",18],
  ["SZ","Swaziland",18],
  ["SE","Sweden",0],
  ["CH","Switzerland",18],
  ["SY","Syria",0],
  ["TZ","Tanzania",18],
  ["TW","Taiwan",18],
  ["TH","Thailand",20],
  ["TG","Togo",18],
  ["TO","Tonga",18],
  ["TT","Trinidad and Tobago",18],
  ["TN","Tunisia",0],
  ["TR","Turkey",24],
  ["TM","Turkmenistan",0],
  ["TV","Tuvalu",18],
  ["UG","Uganda",18],
  ["UA","Ukraine",18],
  ["AE","United Arab Emirates",21],
  ["GB","United Kingdom",18],
  ["US","USA",21],
  ["UY","Uruguay",18],
  ["UZ","Uzbekistan",0],
  ["VU","Vanuatu",18],
  ["VE","Venezuela",18],
  ["VN","Vietnam",18],
  ["YE","Yemen",0],
  ["ZM","Zambia",18],
  ["ZW","Zimbabwe",18]
];


	this.collection = new CountryCollection;
	this.collection.populate( data );
}


AgeGate.prototype = {

	setCountryByIso : function(iso) {
		return this;		
	},

	createBlankOption: function( name ) 
	{
		return this.createOption( '', name );
	},

	createOption: function( value, name )
	{
		var option = document.createElement('option');
		option.text = name;
		option.value = value;
		return option;
	},


	attachToCountry : function( currentSelectObject ) {
		var replacementSelectObject = document.createElement('select');

		replacementSelectObject.name = currentSelectObject.name;
		replacementSelectObject.setAttribute( 'id', currentSelectObject.getAttribute('id') )
		replacementSelectObject.setAttribute( 'class', currentSelectObject.getAttribute('class') )

		try {
			replacementSelectObject.add( this.createBlankOption( 'CHOOSE COUNTRY' ), null  );
		}
		catch (ex)
		{
			replacementSelectObject.add( this.createBlankOption( 'CHOOSE COUNTRY' ), -1  );
		}

		for ( i in this.collection.getCountryArray() )
		{
			var _country = this.collection.getCountryArray()[i];

			try {
				replacementSelectObject.add( _country.createOption(), null ); // not in IE
			}
			catch (ex)
			{
				replacementSelectObject.add( _country.createOption(), -1 ); // not in Firefox
			}
		};

		currentSelectObject.parentNode.replaceChild( replacementSelectObject, currentSelectObject );

		_countrySelect = replacementSelectObject;

		return this;
	},

	attach : function( settings )
	{

		if ( typeof settings.form !== 'undefined' )
		{
			this.attachToForm( document.getElementById(settings.form) );
		}

		if ( typeof settings.country !== 'undefined' )
		{
			this.attachToCountry( document.getElementById(settings.country) );
		}

		if ( typeof settings.day !== 'undefined' )
		{
			this.attachToDay( document.getElementById(settings.day) );
		}

		if ( typeof settings.month !== 'undefined' )
		{
			this.attachToMonth( document.getElementById(settings.month) );
		}

		if ( typeof settings.year !== 'undefined' )
		{
			this.attachToYear( document.getElementById(settings.year) );
		}

		if ( typeof settings.remember !== 'undefined' )
		{
			this.attachToRememberMe( document.getElementById(settings.remember) );
		}

		if ( typeof settings.error !== 'undefined' )
		{
			this.attachToErrorMessageElement( document.getElementById(settings.error) );
		}

	},

	attachToDay : function( currentSelectObject ) {

		var replacementSelectObject = document.createElement('select');

		replacementSelectObject.name = currentSelectObject.name;
		replacementSelectObject.setAttribute( 'id', currentSelectObject.getAttribute('id') )
		replacementSelectObject.setAttribute( 'class', currentSelectObject.getAttribute('class') )

		try {
			replacementSelectObject.add( this.createBlankOption( 'DAY' ), null  );
		}
		catch (ex)
		{
			replacementSelectObject.add( this.createBlankOption( 'DAY' ), -1  );
		}

		for ( var i = 1; i<=31; i++ )
		{

			try {
				replacementSelectObject.add( this.createOption( i, i), null );
			}
			catch (ex)
			{
				replacementSelectObject.add( this.createOption( i, i), -1 );
			}
		};

		currentSelectObject.parentNode.replaceChild( replacementSelectObject, currentSelectObject );

		_daySelect = replacementSelectObject;

		return this;

	},

	attachToMonth : function( currentSelectObject )
	{
		var replacementSelectObject = document.createElement('select');

		replacementSelectObject.name = currentSelectObject.name;
		replacementSelectObject.setAttribute( 'id', currentSelectObject.getAttribute('id') )
		replacementSelectObject.setAttribute( 'class', currentSelectObject.getAttribute('class') )

		try {
			replacementSelectObject.add( this.createBlankOption( 'MONTH' ), null  );
		}
		catch (ex) {
			replacementSelectObject.add( this.createBlankOption( 'MONTH' ), -1  );
		}

		for ( var i = 1; i<=12; i++ )
		{

			try {
				replacementSelectObject.add( this.createOption( i, i), null );
			}
			catch (ex) {
				replacementSelectObject.add( this.createOption( i, i), -1 );
			}
		};

		currentSelectObject.parentNode.replaceChild( replacementSelectObject, currentSelectObject );

		_monthSelect = replacementSelectObject;

		return this;
	},


	attachToYear : function( currentSelectObject ) {

		var replacementSelectObject = document.createElement('select');
	
		replacementSelectObject.name = currentSelectObject.name;
		replacementSelectObject.setAttribute( 'id', currentSelectObject.getAttribute('id') )
		replacementSelectObject.setAttribute( 'class', currentSelectObject.getAttribute('class') )

		try {	  
			replacementSelectObject.add( this.createBlankOption( 'YEAR' ), null  );
		}
		catch( ex )
		{
			replacementSelectObject.add( this.createBlankOption( 'YEAR' ), -1  );
		}

		for ( var year = (new Date).getFullYear(); year >= 1900; year-- )
		{
			try {
				replacementSelectObject.add( this.createOption( year, year), null );
			}
			catch (ex)
			{
				replacementSelectObject.add( this.createOption( year, year), -1 );
			}
		};

		currentSelectObject.parentNode.replaceChild( replacementSelectObject, currentSelectObject );

		_yearSelect = replacementSelectObject;

		return this;

	},

	attachToForm : function(form)
	{
		var that = this;
		form.onsubmit = function()
		{

			var valid = false;

			if ( ! that.userHasCompletedCountry() )
			{
				that.setErrorMessage( 'Please select a country' );
			}
			else if ( ! that.userHasCompletedDob() )
			{
				that.setErrorMessage( 'Please enter a date of birth' );
			}
			else if ( ! that.userCountryIsAllowed() )
			{
				that.setErrorMessage( "Apologies, access to this site has been denied because of the selected country's legal restrictions." );
			}
			else if ( ! that.userIsOldEnough() )
			{
				that.setErrorMessage( 'Apologies, you must be of legal drinking age to enter this site.' );
			}
			else
			{
				that.setCookie();
				valid = true;
			}

			return valid;
		};

		return this;
	},

	setErrorMessage: function( message )
	{
		_errorMessageElement.innerHTML = message;
	},

	userHasCompletedForm : function()
	{
		var valid =
		(
			( _daySelect.selectedIndex !== 0  )
			&&  ( _monthSelect.selectedIndex !== 0 )
			&& ( _yearSelect.selectedIndex !== 0 )
			&& ( _countrySelect.selectedIndex !==0 )
		);

		return valid;
	},

	userHasCompletedDob: function()
	{
		var valid =
		(
			( _daySelect.selectedIndex !== 0  )
			&&  ( _monthSelect.selectedIndex !== 0 )
			&& ( _yearSelect.selectedIndex !== 0 )
		);
		return valid;
	},

	userHasCompletedCountry: function()
	{
		return ( _countrySelect.selectedIndex !==0 );
	},

	userCountryIsAllowed : function()
	{
		return this.collection.getCountryForIso( _countrySelect.value ).isAllowed();
	},

	userIsOldEnough : function()
	{
		return ( this.getAge() >= this.collection.getCountryForIso( _countrySelect.value ).getMinimumAge() );
	},



	isLeapYear: function( year )
	{
		return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
	},

	getAge : function()
	{

		var birthDate = new Date( _yearSelect.value, _monthSelect.value - 1, _daySelect.value );
		var now = new Date();
		var millisecondInNonLeapYears = 86400000;
		var age = 0;
		var daysSinceBirthdate = Math.floor((now.getTime() - birthDate.getTime()) / millisecondInNonLeapYears );

		for (var y = birthDate.getFullYear(); y <= now.getFullYear(); y++)
		{
			var daysInYear = this.isLeapYear(y) ? 366 : 365;
			if (daysSinceBirthdate >= daysInYear)
			{
				daysSinceBirthdate -= daysInYear;
				age++;
			}
		}
		return age;
	},


	attachToRememberMe : function(remember)
	{
		_remember = remember
		return this;
	},

	attachToErrorMessageElement : function(errorMessageElement)
	{
		_errorMessageElement = errorMessageElement;
		return this;
	},

	setCookie : function()
	{
		//var expires = _remember.checked ? ';expires=Tue, 28 Jun 2022 12:26:23 GMT' : '';
		var path = ';path=/';
		var expire = new Date();
		var today = new Date();
		expire.setTime(today.getTime() + 60*60);
		document.cookie = 'ageAgePassed=true;'// + expire.toGMTString() + path;
	},

	loadFromCookie : function()
	{
		var ARRcookies = document.cookie.split(";");

		for ( var i=0;i<ARRcookies.length;i++)
		{
			var x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
			var y = ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
			x = x.replace(/^\s+|\s+$/g,"");

			if ( x == 'dob' )
			{
				this.setDob( unescape(y) );
			}
			else if ( x == 'iso' )
			{
				this.setIso( unescape(y) );
			}
		}
	}

};




