/**
 * @class HD.EventsWidget
 * @description The purpose of EventsWidget is to provide a mechanism to display events. 
 * 				Registered as hd_events_widget.
 * @constructor
 * @extends HD.Widget
 * @see HD.EventsWidget.hooks
 * @see HD.EventsWidget.templates
 * @property {object} 	config
 *                    	The configuration for the widget.
 * @property {object} 	[config.hooks=HD.EventsWidget.hooks]
 *                 		Customized subset of hooks (merged with the defaults).
 * @property {number} 	config.pageSize
 *                    	The number of events to show on a page.
 *                    	Default is 3.
 * @property {string}	config.location
 *                    	Geographic location used to filter events.
 *                    	Default is ''.
 * @property {string} 	config.subtype
 * 					  	Event type used to filter events   
 * 					  	"H-D": Main H-D events
 * 					  	"DLR": H-D dealer events
 * 					  	"HOG": HOG events
 * 					  	"H-D,DLR,HOG": All events
 * 						Default is "H-D,DLR,HOG"
 * @property {boolean}	config.showLocation
 * 						Toggles the user location input on/off.
 * 						Default is false.
 * @property {boolean}	config.handleLinks
 * 						Whether to handle link clicks within the widget 
 * 						(otherwise let viewEvent observers handle it).
 * 						Default is false.
 * @property {boolean}	config.linkToNewWindow
 * 						Whether to open event links in a new window.
 * 						Default is false
 * @property {string}	config.filter
 * 						Additional event filter
 * 						Example: "women" for Women's events.
 * 						Default is ''.
 * @property {boolean}	config.orderByDate
 * 						Whether to order the result by date 
 * 						Default is false (Default order is proximity)
 * @property {object} 	[config.templates=HD.EventsWidget.templates]
 *                 		Customized subset of templates (merged with the defaults).
 */
HD.EventsWidget = function(config) {
    this.config = config || {};
	this.config.pageSize = this.config.pageSize || 3;
	this.config.location = this.config.location || '';
	this.config.subtype = this.config.subtype || 'H-D,DLR,HOG';
	this.config.showLocation = this.config.showLocation || false;
	this.config.handleLinks = this.config.handleLinks == null ? false : this.config.handleLinks;
	this.config.linkToNewWindow = this.config.linkToNewWindow == null ? false : this.config.linkToNewWindow;
	this.config.filter = this.config.filter || '';
	this.config.orderByDate = this.config.orderByDate || false;
	
	/** Observer collection */
    this.observers = [];
	this.addObserver(this);
	
	this.loadTemplates(arguments.callee);
};

/**
 * The collection of default templates.
 * @fieldOf HD.EventsWidget
 */
HD.EventsWidget.templates = {
	
	/**
	 * Label for the widget
	 * @memberOf HD.EventsWidget
	 */
	eventsLabel : 'Events',
	
	/**
	 * Label for the event link
	 * @memberOf HD.EventsWidget
	 */
	viewEventText : 'View Event',
	
	/**
	 * Label for the view all events link
	 * @memberOf HD.EventsWidget
	 */
	viewAllEventsText : 'View All Events',
	
	/**
	 * Label for the location entry box
	 * @memberOf HD.EventsWidget
	 */
	locationLabel : 'Look for events in your area:',
	
	/**
	 * Instructional text for location entry box
	 * @memberOf HD.EventsWidget
	 */
	blankLocationText : 'address, state, city or zip',
	
	/**
	 * Label for the location entry box submit button
	 * @memberOf HD.EventsWidget
	 */
	submitLocationText : 'Go',
	
	/**
	 * @constant
	 * @return {string} Label for the widget: eventsLabel
	 * @memberOf HD.EventsWidget
	 */
	getEventsLabel : function() {
		return this.eventsLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Label for the event link: viewEventText
	 * @memberOf HD.EventsWidget
	 */
	getViewEventText : function() {
		return this.viewEventText;
	},
	
	/**
	 * @constant
	 * @return {string} Label for the view all events link: viewAllEventsText
	 * @memberOf HD.EventsWidget
	 */
	getViewAllEventsText : function() {
		return this.viewAllEventsText;
	},
	
	/**
	 * @constant
	 * @return {string} Label for the location entry box: locationLabel
	 * @memberOf HD.EventsWidget
	 */
	getLocationLabel : function() {
		return this.locationLabel;
	},
	
	/**
	 * @constant
	 * @return {string} Instructional text for location entry box: blankLocationText
	 * @memberOf HD.EventsWidget
	 */
	getBlankLocationText : function() {
		return this.blankLocationText;
	},
	
	/**
	 * @constant
	 * @return {string} Label for the location entry box submit button: submitLocationText
	 * @memberOf HD.EventsWidget
	 */
	getSubmitLocationText : function() {
		return this.submitLocationText;
	},
	
	/**
	 * @constant
	 * @return {string} Main template for the widget
	 * @memberOf HD.EventsWidget
	 */
	getHtml : function() {
		return this.html;
	},
	
	/** 
	 * Main template for the widget
	 * @memberOf HD.EventsWidget
	 * @type jst_template
	 */
	html :  '\
		<div class="${classes.EVENTS} ${classes.WIDGET}">\
			<span class="${classes.TITLE}">${templates.getEventsLabel()}</span>\
			<ul class="${classes.LIST}">\
			{for event in events}\
				<li class="${hooks.ITEMEVENT}">\
					<div class="${classes.ITEM} ${classes.EVENT}">\
						<div class="${classes.SMALL_THUMB_WRAPPER} ${classes.CATEGORY} ${classes.CATEGORY}${event.category[0]}">\
							<div class="${classes.SMALL_THUMB}">\
	 							<div class="${classes.THUMB_OVERLAY}"></div>\
							</div>\
						</div>\
						<div class="${classes.TITLE}">${event.title[0]}</div>\
						<div class="${classes.DATE}">${event|date}&nbsp;&#150;&nbsp;${event|location}</div>\
						<span><a \
							{if config.handleLinks}\
								href="${event.link[0]}" \
							{else}\
								href="#eventAnchor${event_index}" \
							{/if}\
							" \
							{if config.handleLinks && config.linkToNewWindow}\
								target="_blank" \
							{/if}\
						name="eventAnchor${event_index}" class="${classes.VIEW} ${classes.CONTROL}">${templates.getViewEventText()}</a></span>\
					</div>\
				</li>\
			{/for}\
			</ul>\
			{if config.showLocation}\
				<div class="${classes.LOCATION}"><span>${templates.getLocationLabel()}</span>\
					<form class="${hooks.LOCATIONFORM}"><input type="text" class="${hooks.LOCATIONINPUT}" value="{if data.location}${data.location}{else}${templates.getBlankLocationText()}{/if}"/>\
					<a href="javascript:void(0)" class="${hooks.LOCATIONLINK}">${templates.getSubmitLocationText()}</a></form>\
				</div>\
			{/if}\
			<a href="#eventsAnchorAll" name="eventsAnchorAll" class="${classes.VIEW_ALL} ${classes.CONTROL}">${templates.getViewAllEventsText()}</a>\
		</div>'
};

(function() {
	var classes = HD.CSS_CLASSES;
	
	/**
	 * The collection of hooks
	 */
	HD.EventsWidget.hooks = {
		
		/**
		 * Standalone: 0..n<br />
		 * Use: event listing<br />
		 * @memberOf HD.EventsWidget
		 */
		ITEMEVENT : classes.EVENTS + '-item',
		
		/**
		 * Standalone: (1)<br />
		 * Type: form<br />
		 * Use: user location entry container<br />
		 * @memberOf HD.EventsWidget
		 */
		LOCATIONFORM : classes.EVENTS + '-locform',
		
		/**
		 * Standalone: (1)<br />
		 * Type: text input<br />
		 * Use: user location entry box<br />
		 * @memberOf HD.EventsWidget
		 */
		LOCATIONINPUT : classes.EVENTS + '-locinput',
		
		/**
		 * Standalone: (1)<br />
		 * Use: user location entry submission<br />
		 * @memberOf HD.EventsWidget
		 */
		LOCATIONLINK : classes.EVENTS + '-loclink'
	};
})();


HD.EventsWidget.prototype = {
		
	/**
	 * Gets event data for the widget.
	 * @param {string} subtype
	 *                 Event type used to filter events
	 * @param {string} location
	 * 				   Geographic location used to filter events
	 */	
	getFeed : function(subtype, location) {
		var self = this;
		subtype = subtype || this.config.subtype;
		location = location || this.config.location;
		
		this.notifyObservers('getRidePlannerFeed_Events_Start', { subtype: subtype, location: location });
		HD.util.RSS.getRidePlannerFeed('events/' + subtype + '/' + location  + (this.config.filter ? '?filter='+this.config.filter : ''), function(feed) {
			self.notifyObservers('getRidePlannerFeed_Events_Finish', { feed: feed, subtype: subtype, location: location });
		});
	},
    
	/**
	 * Monitors events by HD.EventsWidget.
	 * @param {string} eventName
	 *                 The name of the event
	 * @param {object} [eventData]
	 *                 Data for the event
	 */
    update : function(eventName, eventData) {
    	if(eventName == 'getRidePlannerFeed_Events_Start') {
    		this.loading(true);
    	}
		else if(eventName == 'getRidePlannerFeed_Events_Finish') {
    		this.loading(false);
    		this.render(eventData);
    	}
    },
    
    /**
	 * Sets event listeners for the widget.
	 * @param {object} [data]
	 *                 Event data from the render phase
	 */
    setListeners: function(data) {
		if (!data) {
			return;
		}
	
	   	var classes = HD.CSS_CLASSES;
	   	var parentEl = this.getParent();
		var self = this;
		
		// Grab child elements.
		var items = HD.getByClass(this.config.hooks.ITEMEVENT, '*', parentEl);
    	var viewAll = HD.getByClass(classes.VIEW_ALL, '*', parentEl)[0];
		var feed = data.feed.channel[0];

		var self = this;
		
		// Loop through events and add click observers
		for (var i = 0, limit = Math.min(feed.item.length, this.config.pageSize || 3); i < limit; i++) {
			(function() {
				var item = feed.item[i];
				var fn = function() {
					self.notifyObservers('viewEvent', item);
					return false;
				};
				items[i].onclick = fn;
			})();
    	}
		
		// Attach click observer to view all events link
   		viewAll.onclick = function() {
			self.notifyObservers('viewAllEvents', feed);
			return false;
		};
		
		// Get the Location entry elements
	    var getLocationForm = HD.getByClass(this.config.hooks.LOCATIONFORM, '*', parentEl)[0];
	    var getLocation = HD.getByClass(this.config.hooks.LOCATIONLINK, '*', parentEl)[0];
	    var getLocationInput = HD.getByClass(this.config.hooks.LOCATIONINPUT, '*', parentEl)[0];
			
	    // If this button exists
	    if (getLocation){
		    // Get the event feed with entered location
	    	getLocation.onclick = function() {
				self.getFeed(null, getLocationInput.value);
			};
	    }
		
	    // If the the input box exists
	    if (getLocationInput){
	    	// Remove the default instructional text on user focus
			getLocationInput.onfocus = function() {
				if (this.value == HD.EventsWidget.templates.getBlankLocationText()) {
						this.value = '';
				}
			};
			
			// On user blur
			getLocationInput.onblur = function() {
				// Restore the default instructional text if the box is empty
				if (!this.value) {
					this.value = HD.EventsWidget.templates.getBlankLocationText();
				}
			};
	    }
		
	    // If the form exists
		if (getLocationForm){
			// Get the event feed with entered location on form submission
			getLocationForm.onsubmit = function() {
				self.getFeed(null, getLocationInput.value);
				return false;
			};
		}
		
    },
    
    /**
	 * Renders the HTML for the widget based on dynamic data.
	 * @param {object} [data]
	 *                 Event data from the render phase
	 * @returns {string} HTML for the widget
	 */
    getHtml: function(data) {
		if (!data) {
			return '';
		}
		
		var events = data.feed.channel[0].item;
		var parseDate = /^(.+\s+\d+,\s+\d+)/;
		var parseLocations = /\n\s+(.+)/g;
		var parseLocation = /\n\s+(.+)/;
		
		/** @returns {string} location */
		var generateLocation = function(description) {
			var locations = description.match(parseLocations);
			for (var i = 0; i < locations.length; i++) {
				locations[i] = locations[i].match(parseLocation)[1];
			}
			return locations.join(' ');
		};
		
		// Sort by date if necessary
		if (this.config.orderByDate) {
			events.sort(function(date1,date2) {
				date1.date = date1.description[0].match(parseDate)[0];
				date2.date = date2.description[0].match(parseDate)[0];
				var eventDateA = Date.parse(date1.date);
				var eventDateB = Date.parse(date2.date);
				return eventDateA - eventDateB;
			});
		}

		return this.processTemplate(this.config.templates.getHtml(), {
			data         : data,
			events       : events.slice(0, Math.min(events.length, this.config.pageSize || 3)),
			_MODIFIERS   : {
				date     : function(event) { return event.description[0].match(parseDate)[0]; },
				location : function(event) { return generateLocation(event.description[0]); }
			}
		});
    }
};

HD.extend(HD.EventsWidget, [HD.Widget]);

HD.register('hd_events_widget', 'HD.EventsWidget', {version: "1.0", build: "1"});
