// requires Prototype
// created: 2005-09-23

// 2006-01-20 renamed after_change to after_date_change -- possible incompatibility

/*
Event.observe(window, 'load', function () {
		var labels = document.getElementsByTagName('LABEL')
		for (var i = 0; i < labels.length; ++i) {
			var label = labels[i]
			
			Event.observe(label, 'click', function (event) {
					if (!event) event = window.event
					
					Event.stop(event)

					alert('clicked')
					var inputs = label.getElementsByTagName('INPUT')
					if (inputs) {
						inputs[0].click()
					}
			}, false)
		}
})
*/

Event.observe(window, 'load', function () {
	var inputs = document.getElementsByTagName('INPUT')
	for (var i = 0; i < inputs.length; ++i) {
		var input = inputs[i]
		
		if (Element.hasClassName(input, 'date')) {
			add_calendar_button(input)

			// input.onchange = date_changed
			Event.observe(input, 'change', date_changed)
		}
	}
})

function add_calendar_button(date_input) {
	// Add a button next to the given input that pops up a calendar when clicked.
	
	if ('calendar_button' in date_input) {
		// already there, so do nothing
		return
	}
	
	var button = document.createElement('IMG')
	button.src = '/lib/popcalendar/tigracal.gif'
	button.onclick = function () {
		var allow_past_dates = ! Element.hasClassName(date_input, 'not-past')
		showCalendar(date_input, date_input, 'dd/mm/yyyy', 'en', allow_past_dates)
	}
	button.className = 'popcalendar-open-button'
	
	date_input.parentNode.insertBefore(button, date_input.nextSibling)
	date_input.calendar_button = button
}


function zero_fill(number, length) {
	var numeral = number.toString()
	
	while (numeral.length < length) {
		numeral = '0' + numeral
	}
	
	return numeral
}

function between_inc(value, min, max) {
	// Return true iff value is between min and max, inclusive.
	
	return value >= min && value <= max
}

function dmy_from_date(date) {
	if (!date) return 'dd/mm/yyyy'
	//var dmy = date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear()
	//return dmy
	
	var zf = zero_fill
	//function zf(n, d) { return n }
	
	// calendar uses this format:
	return zf(date.getDate(), 2) + '/' + zf(date.getMonth() + 1, 2) + '/' + zf(date.getFullYear(), 4)
}

function date_from_dmy(dmy) {
	var pieces = dmy.split('/')
	return new Date(pieces[2], pieces[1] - 1, pieces[0])
}

function ensureDate(value) {
	if (value instanceof Date) return value;
	
	return date_from_iso(value);
}


// Custom events to allow multiple things to happen when a date input is changed
// It'd be nice to use the standard DOM interfaces to do this, but IE6 doesn't support them.
// They could be monkeypatched in if it supported Node.prototype... but it doesn't.
// (Adding a behaviour is too cumbersome.)

// Modeled after Prototype's Event.

var CustomEvent = {
	observe: function (target, type, listener) {
		target = $(target);
		
		if (!('customEventListeners' in target)) {
			target.customEventListeners = {};
		}
		
		// create an array to hold the listeners for an event, if it doesn't already exist
		if (!('type' in target.customEventListeners)) {
			target.customEventListeners[type] = [];
		}
		
		// add the new listener only if it's not already there
		if (!(target.customEventListeners[type].include(listener))) {
			target.customEventListeners[type].push(listener);
		}
	},
	
	dispatch: function (target, evt) {
		target = $(target);
		
		// no listeners? do nothing and return
		if (!('customEventListeners' in target)) return;
		if (!(evt.type in target.customEventListeners)) return;
		
		// call each listener with the event
		evt.target = target;
		target.customEventListeners[evt.type].each(function (listener) {
			listener(evt);
		});
	},
	
	stopObserving: function (target, type, listener) {
		target = $(target);
		
		if (!('customEventListeners' in target)) return;
		
		// shorter name
		var listeners = target.customEventListeners;
		
		if (!(type in listeners)) return;
		
		listeners[type].each(function (current_listener, i) {
			if (current_listener == listener) {
				delete listeners[type][i];
				return;
			}
		});
	}
}




function date_changed(event) {
	// A date input has changed: parse and validate its new value.
	
	if (!event) event = window.event
	
	var input = Event.element(event)
	
	var dmy = input.value
	var day, month, year
	var today = new Date()
	
	var pieces = dmy.split(/[-+.\/]/);
	
	day = parseInt(pieces[0], 10)
	if (!between_inc(day, 1, 31)) {
		//alert('Please give the day as a number from 1 to 31')
		//Effect.Highlight(input);
		return;
	}
	
	if (pieces.length >= 2) {
		month = parseInt(pieces[1], 10)
		if (!between_inc(month, 1, 12)) {
			//alert('Please give the month as a number from 1 to 12')
			return
		}
	} else {
		month = today.getMonth() + 1 // counted from 0
	}

	if (pieces.length == 3) {
		year = parseInt(pieces[2], 10)
		if (!between_inc(year, 1, 2100)) {
			//alert('Please give the year as a two-digit or four-digit number')
			return
		}
	} else {
		year = today.getFullYear()
	}
	
	// convert one/two-digit years
	if (year < 100) {
		year += 2000
	}
	
	var date = new Date(year, month - 1, day) // months counted from 0
	
	input.value = dmy_from_date(date);
	

	// now call anything that depends on the new date
	CustomEvent.dispatch(input, {type: 'DateChange'});
	
	
	if ('after_date_change' in input) {
		input.after_date_change();
	}
}

function set_visibility(elem, visible) {
	elem.style.visibility = (visible ? 'visible' : 'hidden')
}

function select_first_control(container) {
	focus_first_control(container, true)
}

function focus_first_control(container, select) {
	elems = container.getElementsByTagName('*')
	for (var i = 0; i < elems.length; ++i) {
		var elem = elems[i]
		if (elem.tagName == 'INPUT' || elem.tagName == 'SELECT' || elem.tagName == 'TEXTAREA') {
			if (elem.tagName == 'INPUT' && elem.type == 'hidden') {
				continue
			}
			
			// found one
			elem.focus()
			if ('select' in elem && select) {
				elem.select()
			}
			return
		}
	}
}

// @@ better names needed

function days_between(start_date, end_date) {
	var MAX_DAYS = 31
	
	for (var days = 0; days <= MAX_DAYS; ++days) {
		var possible_end_day = start_date.getDate() + days
		var possible_end_date = new Date(start_date.getFullYear(), start_date.getMonth(), possible_end_day)
		if (equal_dates(possible_end_date, end_date)) {
			return days
		}
	}
	
	return null
}

function date_add(start_date, days) {
	if (typeof days != 'number') {
		days = parseInt(days);
	}
	
	if (isNaN(days)) {
		return null;
	}
	
	var new_date = new Date(start_date.getFullYear(), start_date.getMonth(), start_date.getDate() + parseInt(days))
	return new_date
}

function equal_dates(first_date, second_date) {
	return (first_date.getFullYear() == second_date.getFullYear()
		&& first_date.getMonth() == second_date.getMonth()
		&& first_date.getDate() == second_date.getDate()
	)
}

function link_date_interval_inputs(start_date_elem, end_date_elem, duration_elem) {
	CustomEvent.observe(start_date_elem, 'DateChange', function () {
		set_end_date_from_start_date_and_duration(end_date_elem, start_date_elem, duration_elem)
		//set_duration_from_dates(duration_elem, start_date_elem, end_date_elem)
	});
	CustomEvent.observe(end_date_elem, 'DateChange', function () {
		set_duration_from_dates(duration_elem, start_date_elem, end_date_elem)
	});
	Event.observe(duration_elem, 'change', function () {
		set_end_date_from_start_date_and_duration(end_date_elem, start_date_elem, duration_elem)
	})
	alert('linked');
}

function set_duration_from_dates(duration_elem, start_date_elem, end_date_elem) {
	var start_date = date_from_dmy($(start_date_elem).value)
	var end_date = date_from_dmy($(end_date_elem).value)
	$(duration_elem).value = days_between(start_date, end_date)
}

function set_end_date_from_start_date_and_duration(end_date_elem, start_date_elem, duration_elem) {
	alert('called');
	var start_date = date_from_dmy($(start_date_elem).value);
	var end_date = date_add(start_date, $(duration_elem).value);
	
	if (end_date) {
		end_date = dmy_from_date(end_date);
	} else {
		end_date = 'unknown';
	}
	
	end_date_elem = $(end_date_elem);
	
	if (['input', 'select'].include(end_date_elem.tagName.toLowerCase())) {
		end_date_elem.value = end_date;
	} else {
		// not a control: let's change its content instead
		end_date_elem.innerHTML = end_date; // does Moz support innerText?
	}
}