/**
 * Javascript utilities for Address validation
 * @author Fabian Camargo
 * @created 2009-12-03
 */
 
var Trooval;
if (!Trooval) Trooval = {};

 // All the code is inside one function which is the only thing added to the Trooval namespace

Trooval.AddressUtilities = function(fields) {
	
// We need jQuery and a JSON object for this to work
if ("undefined" === typeof(jQuery) || "undefined" === typeof(YAHOO.lang.JSON))
{
	return; // don't do anything, no jQuery to work with
}

if ("undefined" === typeof(JSON)) {
	var JSON = YAHOO.lang.JSON;
}


// Check to see if the createStyleSheet function exists (IE Only)
// if it exists then use it to add the CSS Style Sheet, otherwise
// use jQuery. Adding the stylesheet with jQuery doesn't work in IE.
var DEFAULT_STYLESHEET_HREF = "/inc/javascript/address.css";;
if (document.createStyleSheet)
{
	document.createStyleSheet(DEFAULT_STYLESHEET_HREF);
}
else
{
	jQuery("<link>").attr("rel", "stylesheet").attr("href", DEFAULT_STYLESHEET_HREF).appendTo("head");
}

var POPUP_ID = '#addressPopup';

// Define some functions and 'classes'
// needed for Address functionality

Trooval.AddressUtilities.escapeHtmlString = function(text) {
	
	// I couldn't find a built in method to do exactly this
	// We want to at least escape < > & and "
	text = text.replace(/[<>&\"]/g, function(c) {
		switch(c) {
			case '<':
				return "&lt;";
			break;
			case '>':
				return "&gt;";
			break;
			case '&':
				return "&amp;";
			break;
			case '\"':
				return "&quot;";
			break;
		}
	});
	
	return text;
}

// AddressAPI object
Trooval.AddressUtilities.AddressAPI = function(fields) {
	// Record the ids of the form fields, as jQuery selectors
	this.firstNameID = (fields.firstName ? '#' + fields.firstName : null);
	this.lastNameID = (fields.lastName ? '#' + fields.lastName : null);
	this.streetID = (fields.street ? '#' + fields.street : null);
	this.cityID = (fields.city ? '#' + fields.city : null);
	this.stateID = (fields.state ? '#' + fields.state : null);
	this.zipID = (fields.zip ? '#' + fields.zip : null);
	this.form = (fields.form ? $('#' + fields.form).get(0) : null);
	
	// array of suggested addresses
	this.suggestions = new Array();
	
	this.name = "";
	this.address = null;	
}

Trooval.AddressUtilities.AddressAPI.prototype.setAddress = function() {

	// Store the current values of name and address
	
	// Only set the name if it's non-empty
	var lastName = $(this.lastNameID).val();
	var firstName = $(this.firstNameID).val();
	if (lastName && lastName.length > 0 && firstName && firstName.length > 0) // if FN and LN are null or zero-lenght, then don't create a string for the name
		this.name = Trooval.AddressUtilities.escapeHtmlString(firstName + ' ' + lastName);
		
	this.address =new Trooval.AddressUtilities.Address(Trooval.AddressUtilities.escapeHtmlString($(this.streetID).val()),
													   Trooval.AddressUtilities.escapeHtmlString($(this.cityID).val()),
													   Trooval.AddressUtilities.escapeHtmlString($(this.stateID).val()),
													   Trooval.AddressUtilities.escapeHtmlString($(this.zipID).val()));

}

Trooval.AddressUtilities.AddressAPI.prototype.isAddressComplete = function() {
	// Is our address complete?
	return (this.address.isComplete());
}

Trooval.AddressUtilities.AddressAPI.prototype.addSuggestionToPopup = function(suggestion, index) {
	
	// Add a link to this address to the addressList in the popup
	// we add the index of the suggestion in our list to the link
	// so we know what to do when it's clicked
	var addressString = suggestion.toString();
	var addressID = 'address' + String(index);
	var addressLi = "<li id='" + addressID + "' class='validAddress'>";
	addressLi +="<p>CLICK IF THIS IS CORRECT</p>";
	addressLi +="<p>" + this.name + "</p>";
	addressLi +="<p>" + addressString +"</p></li>";
	
	$('#addressList > ol').append(addressLi);
	
	// Variable to hold this so we can call the chooseAddress method
	// in the click handler
	var self = this;
	
	// Add click handler
	$('#'+addressID).click(function(){
		// pass on to addressAPI object
		self.chooseAddress(addressID);
		
		// submit the form
		self.form.submit();
	});
}

Trooval.AddressUtilities.AddressAPI.prototype.addBadAddressLink = function() {

	// Add the link to the bad address with an explanation
	var addressString = this.address.toString();	
	var addressLi = "<li id='badAddress' class='invalidAddress'>";
	addressLi +="<p>WE COULD NOT LOCATE THIS ADDRESS, CLICK TO CORRECT</p>";
	addressLi +="<p>" + this.name + "</p>";
	addressLi +="<p>" + addressString +"</p></li>"; 
	
	
	$('#addressList > ol').append(addressLi);
	
	$('#badAddress').click(function(){
		Trooval.AddressUtilities.disablePopup();	
	}); 
}

Trooval.AddressUtilities.AddressAPI.prototype.addBadAddressFormatLink = function() {

	// Add the link to the bad address with an explanation
	var addressString = this.address.toString();	
	var addressLi = "<li id='badAddress' class='invalidAddress'>";
	addressLi +="<p>THIS ADDRESS IS IN A BAD FORMAT, PLEASE CORRECT</p>";
	addressLi +="<p>" + this.name + "</p>";
	addressLi +="<p>" + addressString +"</p></li>"; 
	
	$('#addressList > ol').append(addressLi);
	
	$('#badAddress').click(function(){
		Trooval.AddressUtilities.disablePopup();	
	});
	
	// In this case the no thanks options shouldn't be available
	$("#nothanks").hide();
}

Trooval.AddressUtilities.AddressAPI.prototype.addGoBackLink = function(){
	
	// The string here depends on whether we have a name or not
	var txt = (this.name.length > 0 ? 'NAME OR ADDRESS' : 'ADDRESS');
	var goBackHtml = "<div id='goBack' class='blue_option'><p>CLICK IF NEED TO EDIT " + txt + "</p></div>";
	$('#addressList').after(goBackHtml);
	
	$("#goBack").click(function(){
		Trooval.AddressUtilities.disablePopup();
	});
}


Trooval.AddressUtilities.AddressAPI.prototype.addHeader = function(){
	// Set the header for the popup
	var txt = (this.name.length > 0 ? 'Name and Address' : 'Address');
	var headerString = 'Verify the ' + txt;
	$('#addressHeader > h2').text(headerString);
}




Trooval.AddressUtilities.AddressAPI.prototype.processResponse = function(response) {
	
	try {
		// Using a parser is safer then using eval to load the json directly
		var responseObj = JSON.parse(response);
	}
	catch (e) {
		
		// If we're not on prod, pop up an alert with the exception
		var host = window.location.host;
		if (host != 'www.trooval.com') {
			alert(e);
		}
		
		// we failed to get address information, we don't want this to stop the form
		// from submitting, so submit it and return
		this.form.submit();
		return;
	}
	
	// start by clearing our suggestions in case we had some before
	this.suggestions = new Array();
	
	for (var i = 0; i < responseObj.Addresses.length;i++) {
		for (var j = 0; j < responseObj.Addresses[i].Suggestions.length; j++) {
			var address = responseObj.Addresses[i].Suggestions[j];
			
			// Create a new address object and add it to
			var suggestion = new Trooval.AddressUtilities.Address(address.Street, address.City, address.State, address.ZipCode);
			
			// Add it to our list of suggestions
			this.suggestions.push(suggestion);
			
			// Add it to the popup
			this.addSuggestionToPopup(suggestion, this.suggestions.length-1);
		}
	}
	
	if (this.suggestions.length == 0 ) {
		// We don't have any suggestions meaning we don't recognize this address
		// Add a link to the bad address
		
		this.addBadAddressLink();
	}
	else {
		this.addGoBackLink();
	}
	
	// Show the popup
	Trooval.AddressUtilities.loadPopup(this);	
}

Trooval.AddressUtilities.AddressAPI.prototype.chooseAddress = function(addressID) {
	// The assumption is that the addressID is a string of the form addressIndex
	
	// extract the index
	var index = addressID.slice(7);
	
	if (index < this.suggestions.length) {
		// Get the suggestion
		var suggestion = this.suggestions[index];
		
		// Populate the form elements with the values from the suggestion
		$(this.streetID).val(suggestion.street);
		$(this.cityID).val(suggestion.city);
		$(this.stateID).val(suggestion.state);
		
		// Qad returns Zip+4, but we only care about 5 digit zip
		if (suggestion.zip.length == 10) {
			suggestion.zip = suggestion.zip.substr(0, 5);
		}
		
		$(this.zipID).val(suggestion.zip);
	}
	
	// either way close the popup
	Trooval.AddressUtilities.disablePopup();
}

// Address class
Trooval.AddressUtilities.Address = function(street, city, state, zip, country) {
	this.street = street;
	this.city = city;
	this.state = state;
	this.zip = zip;
	// Default country to US
	this.country = (country ? country : 'US');
}

/**
 * Returns a single string for the address
 */
Trooval.AddressUtilities.Address.prototype.toString = function() {
	// Construct a string based on our properties
	var fields = [this.street, this.city, this.state, this.zip];
	// remove all empty fields
	for (var i=fields.length-1;i>=0;i--) {
		if (fields[i].length == 0)
			fields.splice(i,1);
	}
	
	return fields.join(', ');
}

Trooval.AddressUtilities.Address.prototype.isComplete = function() {
	// returns true if all the fields are non-empty
	// we leave the actual validation to the qad address API
	// this is just a sanity check, no point looking for an address
	// that doesn't have at least all the fields 
	// Note that we could relax this to only street/zip
	return (this.street.length > 0 &&
			this.city.length > 0 &&
			this.state.length > 0 &&
			this.zip.length > 0);
}



// Methods to control the address popup


//loading popup with jQuery magic!
Trooval.AddressUtilities.loadPopup = function(addressObj) {
	
	Trooval.AddressUtilities.centerPopup(addressObj);

	//loads popup only if it is disabled
	if(popupStatus==0) {
		$(POPUP_ID).show(800);
		popupStatus = 1;
	}
}

//disabling popup with jQuery magic!
Trooval.AddressUtilities.disablePopup = function() {
	
	// Fade the background out
	$("#backgroundPopup").fadeOut("slow");

	//disables popup only if it is enabled
	if(popupStatus==1) {
		$("#backgroundPopup").fadeOut("slow");
		$(POPUP_ID).fadeOut("slow");
		
		// Clear the popup
		Trooval.AddressUtilities.clearPopup();
		popupStatus = 0;
	}
}

Trooval.AddressUtilities.clearPopup = function() {
	// Clear any elements that were added to the popup
	$('#addressList > ol').empty();
	$('#goBack').remove();
}


//centering popup
Trooval.AddressUtilities.centerPopup = function(addresObj) { 
	
	//request data for centering
	var windowWidth = document.documentElement.clientWidth;
	var windowHeight = document.documentElement.clientHeight;
	
	// Set the popup height using a helper function
	var popupHeight = $(POPUP_ID).height();
	var popupWidth = $(POPUP_ID).width();
	
	$("#backgroundPopup").css({
		"height": windowHeight
	});
	
	//centering
	$(POPUP_ID).css({
		"position": "fixed",
		"top": windowHeight/2-popupHeight/2,
		"left": windowWidth/2-popupWidth/2
	});
}

// Function to help us test the popup and formatting
Trooval.AddressUtilities.test = function() {
	// turn test mode on
	testMode = true;
}

Trooval.AddressUtilities.AddressAPI.prototype.test = function()	{
	
	this.addHeader();
	
	// Give ourselves a bad address	
	this.address =new Trooval.AddressUtilities.Address("Superman Dr #1",
													   "Lois' Town",
														"VA",
														"12345");
														
	this.name = "Super, Dude";
	
	// Create a suggestion
	var suggestion = new Trooval.AddressUtilities.Address("Spiderman Lair #1", "Spidey's GF's Town", "CA", "90210");
			
	// Add it to our list of suggestions
	this.suggestions.push(suggestion);
	
	// Add it to the popup
	this.addSuggestionToPopup(suggestion, this.suggestions.length-1);
	
	this.addGoBackLink();
	
	// For testing also add the bad address
	this.addBadAddressLink();	
	
	// Show the popup
	Trooval.AddressUtilities.loadPopup(this);	
}

Trooval.AddressUtilities.setFooterImage = function(companyId) {
	
	// Define map from companyId to imageUrl as a sparse array
	var imageMap = [];
	
	// TODO: uncomment and add when/if we decide to have different images per company
	//imageMap[11] = '/images/westgate-logo.jpg'; 
	
	if (imageMap[companyId] != undefined) {
		// Change the footer to use this image as the background
		var value = "url('" + imageMap[companyId] + "')";
		$('#addressFooter').css('background-image',value);
	} 
}


// Now we start the actual code

// Define state variable needed by the popup methods
// 0 means disabled; 1 means enabled;
var popupStatus = 0;

var testMode = false;

// We want to wait for the document to be fully loaded before we do anything 
$(document).ready(function() {
	
	// if we weren't passed in a form in the fields then there's not much for us to do
	if (fields.form == null || fields.troovalUrl == null)
		return;
	// if we weren't passed in a full address, then we can't really verify it
	if (fields.street == null || fields.city == null || fields.state == null || fields.zip == null)
		return;
	
	// First thing we do is create an addressAPI object passing in the fields that were passed in to us
	var addressAPI = new Trooval.AddressUtilities.AddressAPI(fields);
	
	// Add the html for the popup
	var divHtmlArray = ["<div id='addressPopup'><div id='addressHeader'><h2></h2></div>",
						"<div id='addressList'><ol></ol></div>",
						"<div id='nothanks' class='blue_option'><p>CLICK TO USE THE ADDRESS YOU ORIGINALLY ENTERED</p></div>",
						"<div id='addressFooter'><span>Add Your Logo Here</span></div></div>",
						"<div id='backgroundPopup'></div>"];
						
	// Use an array join to concatenate the html, bit more efficient then repeated string concatenations
	var divHtml = divHtmlArray.join('');
		
	// Add the divHtml to the body
	$('body').append(divHtml);
	
	// Set the footer image
	// We currently don't have any different images so won't call this yet
	/*
	if (fields.companyId != undefined) {
		Trooval.AddressUtilities.setFooterImage(fields.companyId);
	}
	*/
	
	// Special test mode to test formatting
	if (testMode) {
		addressAPI.test();
		return;
	}
	
	// Special code to integrate better with the rm validation classes
	// I wish I knew a way to do this in a more general fashion so that it wouldn't 
	// require any knowledge of the rm code but I haven't figured it out yet
	var rmSubmitHandler = null;
	
	if (rm && rm.Widget && rm.Widget.Form && rm.Widget.Form.onSubmit) {
		// Remember the handler
		rmSubmitHandler = rm.Widget.Form.onSubmit;
		
		// Change the handler to simple function that returns true
		// calling unbind won't work because it wasn't added using jquery
		rm.Widget.Form.onSubmit = function(event, form) { return true;}
	}
			
	// Submit event handler for the form
	$("#" + fields.form).submit(function(event) {
		
		// Make sure the no thanks section is visible by default
		$("#nothanks").show();
		
		// Fade in the background
		$("#backgroundPopup").css({
			"opacity": "0.7"
			});
			
		$("#backgroundPopup").fadeIn("slow");
		
		// Check to see if there's a form validate method defined
		if (rmSubmitHandler) {
			
			if (rmSubmitHandler(event, addressAPI.form) == false) {
				Trooval.AddressUtilities.disablePopup();
				return false;
			}
		}
				
		// Set the address on the addressAPI so it know what the input
		// address was
		addressAPI.setAddress();
		
		// Add the header to the popup
		addressAPI.addHeader();
		
		// If the address isn't fully specified we don't bother calling the qad api
		if (!addressAPI.isAddressComplete()) {
		
			// Add a bad address link
			addressAPI.addBadAddressLink();
			
			// Show the popup
			Trooval.AddressUtilities.loadPopup(addressAPI);
		}
		else {
			// When the form is submitted, we want to make an Ajax/Post
			// call to get the results for the address
			
			var host = window.location.host;
			
			// Post call
			var url = 'http://' + host + '/manager/qad_web_service.php';
			
			try {
				
				$.ajax({ type: 'POST', 
					 	 url: url,
						 data: { txtStreet: addressAPI.address.street,
								 txtCity: addressAPI.address.city,
								 txtState: addressAPI.address.state,
								 txtZip: addressAPI.address.zip,
								 btnVerify: 1
						 },
			 			 success: function(data, textStatus){
								if (textStatus == "success") {
									addressAPI.processResponse(data);
								}
								else 
									alert(textStatus);
				 		 },
						 error: function(requestObject, textStatus, errorThrown) {
							if (requestObject.status == 400) {
								// Bad request error, assume it's a format problem
								// Add a bad address link
								addressAPI.addBadAddressFormatLink();
								
								var addressLi = "<li id='badAddress' class='invalidAddress'>";
								addressLi += requestObject.responseText;
								addressLi +="</li>"; 
								
								$('#addressList > ol').append(addressLi);
								
								// Show the popup
								Trooval.AddressUtilities.loadPopup(addressAPI);
							}
							else {
								// we failed to get address information, we don't want this to stop the form
								// from submitting, so submit it and return
								addressAPI.form.submit();
							}									
						 }
					});
			}
			catch (e) {
				alert(e);
			}
		}
			
		// Return false, we don't want to submit the form until an address is chosen
		return false;
	});
	
	// Add Click handler for NoThanks choice on the popup
	$("#nothanks").click(function(){
		Trooval.AddressUtilities.disablePopup();
		
		// Submit the form
		addressAPI.form.submit();
	});

	// Go back disables the popup without submitting the form	
	$("#goback").click(function(){
		Trooval.AddressUtilities.disablePopup();
	});

});

	
	
}


