/**
 * iaMooEvent.js
 *
 * A Javascript class to interact with the PHP RtEvent object.
 * Namely, this is required for JS event logic regarding interface
 * workflows, displaying appropriate dialogs, etc.
 *
 * @requires MooTools v1.2 - mootools.net
 * 
 * @author Mathias Gran <mathias@inspiringapps.com>
 */
var iaMooEvent = new Class({
	Implements: [Options, Events],
	
	options: {
		dateValidationLocation: '/time/services/schedulerDateValidator.php',
		isPublished: false,
		hasConflict: false,
		hasNotifications: false,
		recordID: 0,
		startStamp: 0,
		setupStartStamp: 0,
		endStamp: 0,
		teardownEndStamp: 0,
		
		fieldErrorClass: 'error' // The css class to use for error state fields.
	},
	
	/** All the elments on the page... populated in initialize. */
	startDate: false,
	startTime: false,
	endDate: false,
	endTime: false,
	setupStartDate: false,
	setupStartTime: false,
	teardownEndDate: false,
	teardownEndTime: false,
	
	initialize: function(options) {
		this.setOptions(options);
		
		this.startDate			= $('event__startDate');
		this.startTime			= $('event__startTime');
		this.endDate			= $('event__endDate');
		this.endTime			= $('event__endTime');
		this.setupStartDate		= $('event__setupStartDate');
		this.setupStartTime 	= $('event__setupStartTime');
		this.teardownEndDate	= $('event__teardownEndDate');
		this.teardownEndTime	= $('event__teardownEndTime');
		
		// Set change events for each field:
		this.attachValidatorEvents();
	},
	
	/**
	 * Sets change events for all scheduler fields.
	 */
	attachValidatorEvents: function() {
		if(!!this.startDate)
		{
			this.startDate.addEvent('change', function() {
				// Auto-update setup start stamp if they started the same:
				if( this.options.setupStartStamp == this.options.startStamp ) {
					this.setupStartDate.value = this.startDate.value;
				}
				
				this.checkOverviewDates();
				
				// Setup has to start prior to event.
				if( this.options.startStamp < this.options.setupStartStamp ) {
					this.setupStartDate.value = this.options.startDate.value;
					this.setupStartTime.value = this.options.startTime.value;
				}
				
				// Start date must be before End date
				if( this.options.startStamp > this.options.endStamp ) {
					this.setEndDate(this.startDate.value);
				}
			}.bind(this));
		}
		
		if(!!this.startTime)
		{
			this.startTime.addEvent('change', function() {
				// Auto-update setup start stamp if they started the same:
				if( this.options.setupStartStamp == this.options.startStamp ) {
					this.setupStartTime.value = this.startTime.value;
				}
				
				this.checkOverviewDates();
			}.bind(this));
		}
		
		if(!!this.endDate)
		{
			this.endDate.addEvent('change', function() {
				// Auto-update teardown end stamp if they end the same:
				if( this.options.teardownEndStamp == this.options.endStamp ) {
					this.teardownEndDate.value = this.endDate.value;
				}
				
				this.checkOverviewDates();
				
				// Auto-update end date if < start date
				if( this.options.startStamp > this.options.endStamp ) {
					this.startDate.value = this.endDate.value;
					if( this.options.setupStartStamp == this.options.startStamp )
					{
						this.setupStartDate.value = this.startDate.value;
					}
				}
				
				// Auto-update teardown end date if < end date
				if( this.options.endStamp > this.options.teardownEndStamp ) {
					this.teardownEndDate.value = this.endDate.value;
				}
			}.bind(this));
		}
		
		if(!!this.endTime)
		{
			this.endTime.addEvent('change', function() {
				// Auto-update teardown end stamp if they end the same:
				if( this.options.teardownEndStamp == this.options.endStamp )
				{
					this.teardownEndTime.value = this.endTime.value;
				}
				
				this.checkOverviewDates();
			}.bind(this));
		}
		
		if(!!this.setupStartDate)
		{
			this.setupStartDate.addEvent('change', function() {
				this.checkOverviewDates();
			}.bind(this));
		}
		
		if(!!this.setupStartTime)
		{
			this.setupStartTime.addEvent('change', function() {
				this.checkOverviewDates();
			}.bind(this));
		}
		
		if(!!this.teardownEndDate)
		{
			this.teardownEndDate.addEvent('change', function() {
				this.checkOverviewDates();
			}.bind(this));
		}
		
		if(!!this.teardownEndTime)
		{
			this.teardownEndTime.addEvent('change', function() {
				this.checkOverviewDates();
			}.bind(this));
		}
	},
	
	/**
	 * Removes change events for all scheduler fields.
	 */
	detachValidatorEvents: function() {
		if(!!this.startDate) {
			this.startDate.removeEvents('change');
		}
		
		if(!!this.startTime) {
			this.startTime.removeEvents('change');
		}
		
		if(!!this.endDate) {
			this.endDate.removeEvents('change');
		}
		
		if(!!this.endTime) {
			this.endTime.removeEvents('change');
		}
		
		if(!!this.setupStartDate) {
			this.setupStartDate.removeEvents('change');
		}
		
		if(!!this.setupStartTime) {
			this.setupStartTime.removeEvents('change');
		}
		
		if(!!this.teardownEndDate) {
			this.teardownEndDate.removeEvents('change');
		}
		
		if(!!this.teardownEndTime) {
			this.teardownEndTime.removeEvents('change');
		}
	},
	
	/**
	 * Makes sure that an error css class is set for each
	 * element in the list of fields provided.
	 * NOTE: Assumes to receive a "short" fieldname.  That is, 
	 * the fieldnames passed must be mapped to the specific
	 * elements used.
	 * @param Array fields
	 */
	highlightFields: function(fields) {
		fields.each(function(field_short){
				switch(field_short) {
					case 'start':
						this.startDate.addClass( this.options.fieldErrorClass );
						this.startTime.addClass( this.options.fieldErrorClass );
						break;
					case 'end':
						this.endDate.addClass( this.options.fieldErrorClass );
						this.endTime.addClass( this.options.fieldErrorClass );
						break;
					case 'setupStart':
						this.setupStartDate.addClass( this.options.fieldErrorClass );
						this.setupStartTime.addClass( this.options.fieldErrorClass );
						break;
					case 'teardownEnd':
						this.teardownEndDate.addClass( this.options.fieldErrorClass );
						this.teardownEndTime.addClass( this.options.fieldErrorClass );
						break;
				}
		}, this);
	},
	
	/**
	 * Removes any error css class from all fields.
	 */
	unhighlightAllFields: function() {
		var allFields = $A([ this.startDate, this.startTime, this.endDate, this.endTime, this.setupStartDate, this.setupStartTime, this.teardownEndDate, this.teardownEndTime ]);
		allFields.each(function(field){
				field.removeClass(this.options.fieldErrorClass);
		}, this);
	},
	
	/**
	 * Shows/Hides the Setup/Teardown container.
	 * Only allows hiding if startStamp == setupStartStamp && endStamp == teardownEndStamp.
	 * Always shows container if they are not the same.
	 * @param string _showhide (optional) May "force" the container to show/hide by passing 'show' or 'hide'.
	 * @todo MOO this code into shape.
	 */
	toggleSetupTearDown: function(_showhide) {
		var _chk = $('chk_showSetupTeardown');
		if( !_chk ) 
		{
			alert('Failed to locate setup/teardown checkbox element.');
			return false;
		}
		
		if( !_showhide )
		{
			_showhide = ( _chk.checked ? 'show' : 'hide' );
		}
		
		if( _showhide != 'hide' ) {
			show( "setupTearDown", "simple" );
			_chk.checked = true;
		}
		else {
			hide( "setupTearDown", "simple" );
			_chk.checked = false;
		}
		
		return false;
	},
	
	/**
	 * Sends all dates from the schedule event overview page to PHP
	 * via AJAX, transforms, then updates form values and shows/hides
	 * the setup/teardown container based on timestamp comparison.
	 */
	checkOverviewDates: function() {
		// Don't do anything if not on the overview page:
		if( !(/\/time\/schedule(\/|\/index\.php|\/\d+\/?)?$/.test(window.location.pathname)) ) {
			//alert('No Match: ' + window.location.pathname);
			return;
		}
		
		// If any of the fields are missing, bail:
		if( !this.startDate 
		||  !this.startTime 
		||  !this.endDate 
		||  !this.endTime 
		||  !this.setupStartDate 
		||  !this.setupStartTime 
		||  !this.teardownEndDate 
		||  !this.teardownEndTime )
		{
			alert('Missing one of the required fields for date validation.');
			return;
		}
		
		//alert('found start date');
		//return;
		
		// Assemble our request data payload here for readability:
		var requestData = {
			'startDate': this.startDate.value,
			'startTime': this.startTime.value,
			'endDate': this.endDate.value,
			'endTime': this.endTime.value,
			'setupStartDate': this.setupStartDate.value,
			'setupStartTime': this.setupStartTime.value,
			'teardownEndDate': this.teardownEndDate.value,
			'teardownEndTime': this.teardownEndTime.value
		};
		
		// Send an ajax request to validate the fields, update the display values, 
		// and show/hide the setup/teardown field.
		var _jax = new Request.JSON({
				url: this.options.dateValidationLocation,
				method: 'get',
				async: false,
				data: requestData,
				onSuccess: function(responseObject, responseText) {
					// Debug:
					//alert(responseText);
					
					// Always alert user messages:
					if( responseObject.userMessage ) {
						alert(responseObject.userMessage);
					}
					
					if( !responseObject.success ) {
						// Failed to process request.
						return false;
					}
					
					// Update stamps in memory:
					this.setOptions(responseObject.options);
					
					// Update display values
					this.startDate.value = responseObject.formattedValues.startDate;
					this.startTime.value = responseObject.formattedValues.startTime;
					this.endDate.value = responseObject.formattedValues.endDate;
					this.endTime.value = responseObject.formattedValues.endTime;
					this.setupStartDate.value = responseObject.formattedValues.setupStartDate;
					this.setupStartTime.value = responseObject.formattedValues.setupStartTime;
					this.teardownEndDate.value = responseObject.formattedValues.teardownEndDate;
					this.teardownEndTime.value = responseObject.formattedValues.teardownEndTime;
					
					// Reset the error state fields:
					this.unhighlightAllFields();
					
					// Evaluate any scripts that may have been passed.
					// Do this prior to displaying dialog, in case of errors
					if( responseObject.js ) {
						//alert(responseObject.js);
						eval(responseObject.js);
					}
					
					// Show the setup/teardown dialog if they are different:
					// Debug:
					//alert( 'Start: '+this.options.startStamp+' SetupStart: '+this.options.setupStartStamp+'\nEnd: '+this.options.endStamp+' TeardownEnd: '+this.options.teardownEndStamp);
					if( this.options.startStamp != this.options.setupStartStamp 
					||  this.options.endStamp   != this.options.teardownEndStamp )
					{
						this.toggleSetupTearDown('show');
					}
					//else
					//{
					//	// Debug:
					//	alert('dates are equal');
					//}
				}.bind(this)
		}).send();
	},
	
	/**
	 * Accepts the new date string from the popup calendar date chooser,
	 * sets the value of the input element, and updates related elements.
	 * @param string dateString The date string supplied by the calendar popup
	 */
	setStartDate: function(dateString) {
		// Detect whether or not to auto-update the end date:
		// - If start DATE (not stamp) == end DATE (not stamp)
		if( this.startDate.value == this.endDate.value ) {
			this.setEndDate(dateString);
		}
		
		if( this.startDate.value == this.setupStartDate.value ) {
			this.setupStartDate.value = dateString;
		}
		
		this.startDate.value = dateString;
	},
	
	/**
	 * Accepts the new date string from the popup calendar date chooser,
	 * sets the value of the input element, and updates related elements.
	 * @param string dateString The date string supplied by the calendar popup
	 */
	setEndDate: function(dateString) {
		// Detect whether or not to auto-update the teardown stamp end date:
		// - If teardown end DATE (not stamp) == end DATE (not stamp)
		if( this.teardownEndDate.value == this.endDate.value ) {
			this.teardownEndDate.value = dateString;
		}
		
		this.endDate.value = dateString;
	},
	
	/**
	 * Accepts the new date string from the popup calendar date chooser,
	 * sets the value of the input element, and updates related elements.
	 * @param string dateString The date string supplied by the calendar popup
	 */
	setSetupStartDate: function(dateString) {
		this.setupStartDate.value = dateString;
	},
	
	/**
	 * Accepts the new date string from the popup calendar date chooser,
	 * sets the value of the input element, and updates related elements.
	 * @param string dateString The date string supplied by the calendar popup
	 */
	setTeardownEndDate: function(dateString) {
		this.teardownEndDate.value = dateString;
	}
});
