// States must have the state ID as an "value" or "title" or "class" attribute (letters are ignored).
// Format: COUNTRY_ID: [stateIdFrom, stateIdTo, zipPattern, zipError], ...
window.xFormStates={
	124: [60, 89, /[A-Z]\d[A-Z] \d[A-Z]\d/i, 'Enter the ZIP code in this format: A0A 0A0'], // Canada
	CA: [60, 89, /[A-Z]\d[A-Z] \d[A-Z]\d/i, 'Enter the ZIP code in this format: A0A 0A0'], // Canada
  
	840: [ 0, 59, /^(\d{5}-\d{4}|\d{5}|\d{9})$|^([A-Z]\d[A-Z] \d[A-Z]\d)$/i, 'Enter the ZIP code in this format: 12345 or 12345-1234'],  // United States
	US: [ 0, 59, /^(\d{5}-\d{4}|\d{5}|\d{9})$|^([A-Z]\d[A-Z] \d[A-Z]\d)$/i, 'Enter the ZIP code in this format: 12345 or 12345-1234'],  // United States
  
	826: [90, 189, /.*/, 'any string'], // United Kingdom's counties
	UK: [90, 189, /.*/, 'any string'], // United Kingdom's counties
  
	484: [190, 229, /.*/, 'any string'], // Mexico
	MX: [190, 229, /.*/, 'any string'] // Mexico  
};
    
/**
 * Put something like this in your XFrom's layout:
 *
 * <script src="/scripts/xforms/xformstates.js" type="text/javascript"/>  
 * <script type="text/javascript">initXFormStates("1136914547", "1136914562", "hideIt");</script>
 *
 * @access private
 * @param string countryId The numeric number of the field in XForm
 * @param string stateId  The numeric number of the field in XForm
 * @param stateBlockId the ID attribute of the HTML to hide if no states available.
 * @param otherStatesBlockId the optional ID attribute of the HTML to display when no known states are available (window.xFormStates is not defined for given country)
 * @param zipId ID of the ZIP field. Will be validated based on the Country type.
 * @return void
 */
function initXFormStates(countryId, stateId, stateBlockId, otherStatesBlockId, zipId) {
	// Find country
	var country=document.getElementById(countryNodeId='xFormField'+countryId);
	var state=document.getElementById(stateNodeId='xFormField'+stateId);
	var zip=document.getElementById(zipNodeId='xFormField'+zipId);	

	// Check
	if (!country) alert('Country field with id "'+countryNodeId+'" not found!');
	if (!state) alert('State field with id "'+stateNodeId+'" not found!');

	// Install listener
	country.onchange=function() {updateXFormStates(countryId, stateId, stateBlockId, otherStatesBlockId);};
	country.form.onsubmit=function() {return validateXFormZIP(countryId, zipId) && validateXFormStates(countryId, stateId, stateBlockId, otherStatesBlockId);};

	if (zip) zip.onchange=function() {validateXFormZIP(countryId, zipId);};

	// MORON IE CANNOT HIDE ITEMs IN SELECT - MUST REMOVE THEM FROM THE DOM
	// Remove all from the list
	state.stateList=[];
	for(var i=state.childNodes.length - 1; i >= 0; i--) {
	    if (state.childNodes[i].nodeType==1) {
		state.stateList.push(state.childNodes[i]);
	    }
	}
	updateXFormStates(countryId, stateId, stateBlockId, otherStatesBlockId);
	if(typeof jQuery == 'function') {
		jQuery(function() {updateXFormStates(countryId, stateId, stateBlockId, otherStatesBlockId);});
	}
}

function updateXFormStates(countryId, stateId, stateBlockId, otherStatesBlockId) {
	// Find the elements
	var country=document.getElementById(countryNodeId='xFormField'+countryId);
	var state=document.getElementById(stateNodeId='xFormField'+stateId);
	var stateBlock=document.getElementById(stateBlockId);
	var otherStatesBlock=document.getElementById(otherStatesBlockId);	

	// Nothing selected - hide all
	if (!country.value) {
		setHiddenProperty(state);		
		stateBlock && (setHiddenProperty(stateBlock));
		otherStatesBlock && (setHiddenProperty(otherStatesBlock));
		return;
	}

	// No states - display only OTHER STATE if any
	if (window.xFormStates[country.value] == undefined) { 
		state.selectedIndex=0;
		state.disabled=true; // Otherwise it won't be submitted (if display: none)
		setHiddenProperty(state);
		stateBlock && (setHiddenProperty(stateBlock));
		otherStatesBlock && (unsetHiddenProperty(otherStatesBlock));		
		return;
	} 

	// Show relevant
	unsetHiddenProperty(state);
	stateBlock && (unsetHiddenProperty(stateBlock));
	otherStatesBlock && (setHiddenProperty(otherStatesBlock));			
	state.disabled=false;
	var from=window.xFormStates[country.value][0];
	var to=window.xFormStates[country.value][1];
	var itemValue;

	removeAllChildren(state);
	for(var i=state.stateList.length - 1; i >= 0; i--) {
		itemValue=parseInt(state.stateList[i].value);
		if (!itemValue && state.stateList[i].className) itemValue=parseInt(state.stateList[i].className.replace(/[^0-9]/, ''));
		if (!itemValue && state.stateList[i].getAttribute && state.stateList[i].getAttribute('title')) itemValue=parseInt(state.stateList[i].getAttribute('title').replace(/[^0-9]/, ''));
		
		if (!itemValue || (from <= itemValue && itemValue <= to)) { // show
			state.appendChild(state.stateList[i]);
		}
	}

	// Reset seletion
	if (state.value > to || state.value < from) state.value="";
}

function removeAllChildren(node) {
  for(var i=node.childNodes.length - 1; i >= 0; i--) {
		node.removeChild(node.childNodes[i]);
	}
}

function validateXFormStates(countryId, stateId, stateBlockId) {
	// Find the elements
	var country=document.getElementById(countryNodeId='xFormField'+countryId);
	var state=document.getElementById(stateNodeId='xFormField'+stateId);
	var stateBlock=document.getElementById(stateBlockId);

	// This hack should not be here, it should work with state.childNodes.length only
	//if (country.value==840) {
	    if (stateBlock.style.display != 'none' && state.childNodes.length && !state.value) {
		alert('Select the state, please.');
		return false;
	    }
	    //}

	return true;
}

function validateXFormZIP(countryId, zipId) {
	if (!zipId) return true;

	var country=document.getElementById(countryNodeId='xFormField'+countryId);
	var zip=document.getElementById(zipNodeId='xFormField'+zipId);	
	var pattern=window.xFormStates[country.value] && window.xFormStates[country.value][2];
	
	if (!pattern) return true;

	if (zip.value.replace(/\s+/, '').length && !zip.value.match(pattern)) {
		alert(window.xFormStates[country.value][3]);
		return false;
	}
	
	return true;
}

function unsetHiddenProperty(node) {
	if (typeof node.style.removeProperty == 'function') {
		node.style.removeProperty('display');
	} else {
		node.style.display='block';
	}
}

function setHiddenProperty(node) {
	node.style.display='none';
}
