/**
 * Albertsons Core
 * Version 1.0.0 - 11/22/2008
 * @author Benjamin Truyman
 **/

/**
 * Albertsons namespace
 **/
var ABS = {};

ABS = {
	initialize: function () {
		// Allows for targeting CSS selectors for users with JavaScript enabled
		$('body').addClass('has_script');
		ABS.Managers.Popup.initialize();
	}
};

// Helper namespace
ABS.Helpers = {};

// Analytics helper
ABS.Helpers.Analytics = {
	options: {},
	trackers: {},
	initialize: function (options) {
		// Set options
		if (options.account === undefined) {
			throw new Error('Account number must be defined for Analytics helper.');
		} else {
			this.options.account = options.account;
		}
		if (options.autoTrackPageView === false && options.autoTrackPageView !== undefined) {
			this.options.autoTrackPageView = options.autoTrackPageView;
		} else {
			this.options.autoTrackPageView = true;
		}
		if (options.propSalt === undefined) {
			this.options.propSalt = 'svu';
		} else {
			this.options.propSalt = options.propSalt;
		}
		if (options.props !== undefined) {
			this.props = options.props;
		};
		
		// Download analytics JavaScript core
		this.downloadScript();
		
		// Execute routines when analytics JavaScript has been downloaded
		$(this).bind('scriptReady', ABS.Utils.Delegate.create(this, function (e) {
			this.buildTracker();
			if (this.options.autoTrackPageView) this.trackPageView();
		}));
	},
	downloadScript: function () {
		var that = this;
		var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
		$.getScript(gaJsHost + 'google-analytics.com/ga.js', function () {
			$(that).trigger('scriptReady');
		});
	},
	buildTracker: function () {
		// Try to create tracker
		try {
			this.trackers.page = _gat._getTracker(this.options.account);			
		} catch(err) {}
	},
	buildURL: function (href) {
		// Define placeholder variables
		var path, tags = '';
		if (href) {
			path = href;
		} else {
			path = window.location.pathname + window.location.search;
		}
		
		// Add page properties to path
		if (this.props) {
			// Build prop query string
			for (prop in this.props) {
				tags += '&' + this.options.propSalt + '_' + prop + '=' + this.props[prop];
			}
			// Determine if a query string already exists in the path
			var regexp = new RegExp(/^.*?\?/);
			if (!path.match(regexp)) {
				tags = '?' + tags.substr(1, tags.length);
			}
		}
		
		return String(path + tags);
	},
	trackEvent: function (category, action, label, value) {
		// Check for arguments
		if (category === undefined || action === undefined) {
			throw new Error('A category and action must be provided in order to track an event with the Analytics helper.');
		} else {
			this.trackers.page._trackEvent(category, action, label, value);
		}
	},
	trackPageView: function (href) {
		if (href) {
			this.trackers.page._trackPageview(this.buildURL(href));
		} else {
			this.trackers.page._trackPageview(this.buildURL());
		}
	}
};

// Form Validation helper
ABS.Helpers.FormValidator = function (params) {
	var that = this;

	// Check for required values
	if (typeof params.form === 'undefined') {
		throw new Error('Form element must be defined.');
	}
	
	// Regular expression patterns
	this.patterns = {
		email: /([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/,
		trim: /^[ \t]+|[ \t]+$/,
		zip: /^\d{5}([\-]\d{4})?$/
	};
	
	// Validators
	this.hasMinLength = function (str, length) {
		if (str.length >= length) {
			return true;
		}
		return false;
	};
	
	this.hasMaxLength = function (str, length) {
		if (str.length <= length) {
			return true;
		}
		return false;
	};
	
	this.isEmail = function (str) {
		if (str.match(this.email) !== null) {
			return true;
		}
		return false;
	};
	
	this.isEmpty = function (str) {
		str = str.replace(this.patterns.trim, '');
		if (str !== '') {
			return true;
		}
		return false;
	};
	
	this.isZIP = function (str) {
		if (str.match(this.patterns.zip) !== null) {
			return true;
		}
		return false;
	};
	
	this.validate = function (dom, options) {
		// Get elements value
		var value = $(dom).val();
		
		// Begin checking options
		if (
				(options.email === true && !this.isEmail(value)) ||
				(typeof options.minLength !== 'undefined' && !this.hasMinLength(value, options.minLength)) ||
				(typeof options.maxLength !== 'undefined' && !this.hasMaxLength(value, options.maxLength)) ||
				(options.required === true && !this.isEmpty(value)) ||
				(options.zip === true && !this.isZIP(value))
			) {
			return false;
		}
		
		return true;
	};
	
	// Return validator object
	return {
		form: params.form,
		elements: params.elements,
		run: function () {
			var self = this;
			var returns = {
				areValid: true,
				elements: {
					failed: [],
					passed: []
				}
			};
			$(this.elements).each(function () {
				// Create temporary variable for current form element
				var element = $(self.form).find('[name="' + this.name + '"]').get(0);
				
				// Validate current element
				if (that.validate(element, this.options) === true) {
					returns.elements.passed.push(element);
				} else {
					returns.elements.failed.push(element);
				}
			});
			
			// Set entire form validation status (convenience variable)
			returns.areValid = returns.elements.failed.length > 0 ? false : true;
			
			return returns;
		}
	};
};

// Manager namespace
ABS.Managers = {};

ABS.Managers.Popup = {
	container: null,
	
	initialize: function () {
		// Build Popup Manager
		this.build();
	},
	
	build: function () {
		// Build Popup Manager if hasn't been built yet
		if (this.container === null) {
			this.container = $('<div id="popup-manager"></div>').appendTo('#container').get(0);
		}
	},
	
	add: function (dom) {
		this.build();
		return $(dom).appendTo(this.container).get(0);
	},
	
	remove: function (id) {
		return $('#' + id, this.container).remove();
	}
};

// User Interface namespace
ABS.UI = {};

// Utility namespace
ABS.Utils = {};

// Event Delegate
ABS.Utils.Delegate = {
	create: function (obj, func) {
		return function (e) {
			e = e || {};
			// Forces currentTarget property of the Event object for browsers that don't correctly support it
			e.currentTarget = this;
			// Call function within context of specified object
			func.apply(obj, [e]);
		};
	}
};

// Image Preloader
ABS.Utils.ImagePreloader = {
	paths: [],
	
	add: function (path) {
		var that = this;
		if (typeof path === 'String') {
			this.paths.push(path);
		} else if (typeof path === 'object'){
			$(path).each(function () {
				that.paths.push(this);
			});
		}
	},
	
	load: function () {
		// Load images into empty elements
		$(this.paths).each(function () {
			jQuery('<img>').attr('src', this);
		});
		
		// Clear out paths cache
		this.paths = [];
	}
};

// Dummy event handler that prevents default event behavior
ABS.Utils.dummyEventHandler = function (e) {
	e.preventDefault();
};

$(document).ready(function () {
	// Initialize common methods
	ABS.initialize();
	
	// Preload images
	ABS.Utils.ImagePreloader.add([
		'img/common/backgrounds/store-finder-popup.png',
		'img/common/backgrounds/store-finder-popup.gif',
		'img/common/backgrounds/callout-short.png',
		'img/common/backgrounds/callout-short.gif'
	]);
	ABS.Utils.ImagePreloader.load();
});