/**
 * Static Cookie functions
 */
var Cookie = {
	// default values
	days: 30, path: '/',
	// set a cookie, returns its value
	set: function setCookie(name, value, days, path) {
		days = days ? days : Cookie.days;
		path = path ? path : Cookie.path;
		if(typeof name != 'undefined' && typeof value != 'undefined') {
			document.cookie = name+'='+value+'; expires='+
				Cookie.getTimeFromDays(days)+'; path='+path;
			return value;
		}
		return null;
	},
	// get the value of a cookie
	get: function getCookie(name) {
		if(( result = $A(document.cookie.split('; ')).find(function(cookie) {
				return cookie.startsWith(name);
			}) )) {
			return result.replace(result.split('=').first()+'=', '');
		}
		return null;
	},
	// unset/remove a cookie
	unset: function unsetCookie(name) { Cookie.set(name,'', -1); },
	// get correctly formatted timestamp relative to now with the specified days:
	getTimeFromDays: function getTimeFromDays(days) {
		var date = new Date();
		date.setTime(date.getTime()+(60*60*24*days*1000));
		return date.toGMTString();
	}
};

/**
 * Stylemanager
 * Creates a list for all selectable stylesheets in the given container
 * Usage: new StyleManager(<container element>, modus[, name]);
 * - Modus will default to 'toggle' creating a switch between 2 stylesheets
 *   Setting modus to 'list' will create a dropdown list making it possible
 *   to switch between more than 2 stylesheets.
 * - Name is only used when modus is set to 'list'
 */
var StyleManager = Class.create({
	stylesheets: null,
	activeLink: false,
	title: null,
	element: null,
	cookieName: 'stylesheet',
	initialize: function(container, modus, name) {
		this.modus = modus ? modus  : 'toggle';
		this.stylesheets = $$('head link[title]');
		this.element = this.modus == 'toggle' ? new Element('span').addClassName('sizetoggles') : new Element('ul').addClassName('stylelist');
		// create the title
		if(this.modus != 'toggle') {
			this.title = new Element('a',{href:'#styles'}).addClassName('selectedstyle')
				.observe('click', function toggleList(event) {
					event.stop(); this.element.toggle();
				}.bindAsEventListener(this));
		}
		// get and set the active stylesheet
		if(!(activeTitle = Cookie.get(this.cookieName)) ||  this.stylesheets.pluck('title').indexOf(activeTitle) == -1) {
			if( (link = this.stylesheets.find(function(link) {
				return (link.readAttribute('rel').indexOf('alternate') == -1);
			})) ) { activeTitle = link.readAttribute('title'); }
		}
		this.setActive(activeTitle);
		// add all the style options
		this.stylesheets.each(function(link) {
			var a = new Element('a',{href: '#'+link.readAttribute('title')})
				.update(link.readAttribute('title'));
			if(this.modus == 'toggle' && link.hasClassName('toggle')) { // stylesheet is a toggle, add to toggles
				a.observe('click', this.toggleStylesheet.bindAsEventListener(this, link.readAttribute('title')));
				this.element.insert(a);
				a.addClassName(link.classNames());
				if(this.activeLink.readAttribute('title') == link.readAttribute('title')) {
					a.addClassName('active');
				}
			} else if(this.modus != 'toggle') { // add to styles selectbox
				a.observe('click', this.selectStylesheet.bindAsEventListener(this, link.readAttribute('title')));
				var li = new Element('li').insert(a);
				if(this.activeLink.readAttribute('title') == link.readAttribute('title')) {
					li.addClassName('active');
				}
				this.element.insert(li);
			}
		}, this);
		// insert the control in the page
		if(this.modus == 'toggle') {
			$(container).insert({top: this.element});
		} else {
			$(container).insert({
				top: new Element('span').update(name).insert({bottom: this.title}),
				bottom: this.element.hide()
			});
		}
	},
	toggleStylesheet: function toggleStylesheet(event, title) {
		event.stop();
		event.findElement('a').addClassName('active')
			.adjacent('a').invoke('removeClassName', 'active');
		this.setActive(title);
	},
	selectStylesheet: function selectStylesheet(event, title) {
		event.stop();
		event.findElement('li').addClassName('active')
			.adjacent('li').invoke('removeClassName', 'active');
		this.setActive(title);
		this.element.hide();
	},
	setActive: function setActive(title) {
		this.stylesheets.each(function(link) {
			link.disabled = true;
			if(link.readAttribute('title') == title) {
				link.disabled = false;
				Cookie.set(this.cookieName, title);
				if(this.title) {
					this.title.update(title);
				}
				this.activeLink = link;
			}
		}, this);
		return this.activeLink;
	}
});

/**
 * Generic tabs class to convert a list element with either a or label elements to a tab structure
 * Usage: new Tabs(<list element>[, options]);
 * Options:
 * Which classnames to apply:
 * - hiddenClassName (default: 'hidden'): className applied to hidden/inactive tab bodies
 * - selectedClassName (default: 'selected'): className applied to selected/active tabs
 * - disabledClassName (default: 'disabled'): className for disabled tabs, these tabs won't trigger
 * Which elements to use:
 * - tabSelector (default: 'li'): selector used for the tabs
 * - linkSelector (default: 'a'): selector used for the link in the tab (a or label)
 * - contentSelector (default: '.tab'): shared selector used by all tab bodies
 * What to select on load:
 * - useHash (default: true): selects the tab using the document.location.hash
 * - selectFirst (default: true): if true the first tab will be selected if no others are.
 */
var Tabs = Class.create({
	list: null,
	options: {
		classNames: {
			hidden: 'hidden', selected: 'selected', disabled: 'disabled'
		},
		selectors: {
			tab: 'li', link: 'a', content: '.tab'
		},
		useHash: true,
		selectFirst: true
	},
	initialize: function(list, options) {
		this.list = $(list);
		if(this.list.hasClassName('istabs')) { return; } // don't allow duplicates
		this.options = options ? {
			classNames: {
				hidden: options.hiddenClassName || this.options.classNames.hidden,
				selected: options.selectedClassName || this.options.classNames.selected,
				disabled: options.disabledClassName || this.options.classNames.disabled
			},
			selectors: {
				tab: options.tabSelector || this.options.selectors.tab,
				link: options.linkSelector || this.options.selectors.link,
				content: options.contentSelector || this.options.selectors.content
			},
			selectFirst: options.selectFirst || this.options.selectFirst,
			useHash: options.useHash || this.options.useHash
		} : this.options;
		// add observers
		this.list.select(this.options.selectors.link).invoke('observe', 'click', function clickEventHandler(event) {
			if(this.click(event.findElement(this.options.selectors.link))) {
				event.stop();
			}
		}.bindAsEventListener(this));
		this.list.select('input[type=radio]').invoke('observe', 'click', function radioEventHandler(event) {
			this.click(event.findElement(this.options.selectors.tab).down(this.options.selectors.link));
		}.bindAsEventListener(this));
		// select preferred:
		var sLink = this.options.selectors.link;
		var hash = document.location.hash.replace('#','');
		if(this.options.useHash && !hash.empty() &&
			(selected = this.list.down(sLink + '[href$='+hash+'], ' + sLink+'[for$='+hash+']'))) {
			this.click(selected);
		} else if(this.options.selectFirst &&
			(selected = this.list.down(this.options.selectors.tab +
				'.'+this.options.classNames.selected) || (selected = this.list)) ) {
			this.click(selected.down(sLink));
		}
		this.list.addClassName('istabs'); // we're done
	},
	click: function clickTab(tab) {
		var item = tab.up(this.options.selectors.tab);
		if(item.hasClassName(this.options.classNames.disabled)) {
			return true;
		} else {
			item.addClassName(this.options.classNames.selected)
			.adjacent(this.options.selectors.tab).invoke('removeClassName', this.options.classNames.selected);
			if( (input = item.down('input[type=radio]') )) {
				input.checked = 'checked';
			}
		return this.select(this.getTargetId(tab));
		}
	},
	select: function selectTab(id) {
		if( (target = $(id)) ) {
			return target.removeClassName(this.options.classNames.hidden)
				.adjacent(this.options.selectors.content).invoke('addClassName', this.options.classNames.hidden);
		} else { return false; }
	},
	getTargetId: function getTargetId(source) {
		var id = source;
		if(Object.isElement(source)) {
			switch(source.tagName.toLowerCase()) {
				case 'a': id = source.readAttribute('href').split('#').last(); break;
				case 'label': id = source.readAttribute('for'); break;
			}
		}
		return id;
	}
});

/**
 * Class to add observers to clear and fill an element on focus and blur
 * Usage: new FocusClear(<input element>);
 * By default it's possible to add the class 'focusclear' to an input and you're done
 */
var FocusClear = Class.create({
	value: null,
	initialize: function(input) {
		this.input = $(input); this.value = $F(input);
		input.observe('focus', this.focus.bindAsEventListener(this))
			.observe('blur', this.blur.bindAsEventListener(this));
	},
	focus: function focusInput(event) {
		if($F(this.input) == this.value) {
			this.input.removeClassName('focusclear').setValue('');
		}
	},
	blur: function blurInput(event) {
		if($F(this.input).blank()) {
			this.input.addClassName('focusclear').setValue(this.value);
		}
	}
});

/**
 * Toggle's the reaction and adds observers to the link
 * Also checks if the form has been submitted by matching the err url parameter
 */
var ReactionForm = Class.create({
	form: null,
	initialize: function() {
		if( (this.form = $('react-form')) ) {
			if(document.location.href.match(/react=true/) && document.location.href.match(/err=[0-9]/)) {
				this.form.scrollTo().focusFirstElement();
			} else {
				this.form.addClassName('hidden');
			}
			this.form.select('a.close').invoke('observe', 'click', function(event) { event.stop(); event.findElement('form').addClassName('hidden'); });
			$$('a.link_reaction').invoke('observe', 'click', this.toggleForm.bindAsEventListener(this));
		}
	},
	toggleForm: function toggleForm(event) {
		event.stop();
		this.form.toggleClassName('hidden');
		if(!this.form.hasClassName('hidden')) {
			this.form.down('input[type=text]').focus();
		}
	}
});

/**
 * Google Maps v3 class
 * Automaticly loads the google api (no api key required)
 * Usage: new GoogleMap(container[, onCreate]);
 * 
 */
var GoogleLoadedCallback = Prototype.K;
var GoogleMap = Class.create({
	// settings:
	maxZoom: false,
	// elements:
	container: null, element: null,
	// map objects
	map: null, points: null, markers: null, bounds: null, infoWindows: null,
	// callbacks:
	onCreate: function(){},
	initialize: function initialize(container, onCreate) {
		var e;
		this.container = $(container);
		if(onCreate){this.onCreate = onCreate;}
		this.infoWindows = $A();
		this.markers = $A();
		this.element = new Element('div').clonePosition(this.container,{setLeft:false,setTop:false});
		this.container.insert({top: this.element});
		this.maxZoom = (e = this.container.down('span.max-zoom')) ? parseInt(e.hide().innerHTML) : this.maxZoom;		
		if(typeof google == 'undefined') {
			this.loadGoogleAPI();
		} else {
			this.create();
		}
	},
	loadGoogleAPI: function loadGoogleAPI() {
		GoogleLoadedCallback = this.create.bind(this);
		$$('head').invoke('insert', new Element('script', {
			src: 'http://maps.google.com/maps/api/js?sensor=false&callback=GoogleLoadedCallback',
			type: "text/javascript"
		}));
	},
	create: function create() {
		this.bounds = new google.maps.LatLngBounds();
		this.map = new google.maps.Map(this.element, {
			mapTypeId: google.maps.MapTypeId.ROADMAP
		});
		this.addData();
		this.onCreate();
	},
	setCenter: function setCenter(lat, lng) {
		if(typeof lat.lat == 'number') {
			lat = new google.maps.LatLng(lat, lng);
		}
		this.map.setCenter(lat);
	},
	getZoom: function getZoom() { return this.map.getZoom(); },
	setZoom: function setZoom(zoom) { return this.map.setZoom(zoom); },
	checkMaxZoom: function checkMaxZoom() {
		if(this.maxZoom && this.getZoom() > this.maxZoom) {
			this.setZoom(this.maxZoom);
		}
	},
	addData: function addData() {
		this.container.select('span.coordinate').invoke('hide').pluck('innerHTML').map(this.strToLatLng)
			.each(function(point) {
				this.bounds.extend(point);
				this.addMarker(point);
			}.bind(this));
		this.fitBounds();
	},
	addMarker: function addMarker(LatLng, markerOptions) {
		var defaultOptions = { position: LatLng, map: this.map };
		var marker = new google.maps.Marker(markerOptions ? $H(defaultOptions).merge(markerOptions).toObject() : defaultOptions);
		this.markers.push(marker);
		return marker;
	},
	fitBounds: function fitBounds(bounds) {
		this.map.fitBounds(bounds ? bounds : this.bounds);
		this.checkMaxZoom.bind(this).delay(0.5);
	},
	centerBounds: function centerBounds(bounds) {
		bounds = bounds ? bounds : this.bounds;
		this.map.setCenter(bounds.getCenter());
	},
	strToLatLng: function strToLatLng(value) {
		var coords = value.replace('/\s//g').split(',').map(function(i) {return parseFloat(i);});
		return (!isNaN(coords[0]) && !isNaN(coords[1])) ? new google.maps.LatLng(coords[0], coords[1]) : null;
	}
});

/**
 * Returns the version of internet explorer or false if it's not IE
 */
function getIEVersion() {
	if(Prototype.Browser.IE) {
		var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
		if (re.exec(navigator.userAgent) != null)
			return parseFloat(RegExp.$1);
	}
	return false;
}

/**
 * Support for legacy global functions
 */
function readCookie(name) { return Cookie.get(name); }
function createCookie(name,value,days) { return Cookie.set(name, value, days); }
function ShowHideDivs(show,hide) { $(show).show(); $(hide).hide(); }

/**
 * dom:loaded event
 */
document.observe('dom:loaded', function domloaded() {
	// Create the stylemanager:
	var header;
	if( (header = $('header')) ) {
		var stylecontainer = new Element('div', {id: 'fontsize'});
		header.insert({after: stylecontainer});
		new StyleManager(stylecontainer, 'toggle', 'Site stijl: ');
	}
	// reaction form:
	new ReactionForm();
	// pagelinks:
	if( (pageLinks = $('page_links')) ) {
		// create printlink
		var printlink = new Element('a', {href: '#print'}).addClassName('link_print')
			.update('Print pagina')
				.observe('click', function(event) { event.stop(); window.print(); });
		if((sb = $('social-bookmarks'))) {
			sb.insert({after: printlink});
		} else {
			pageLinks.insert({top: printlink});
		}
	}
	// maps:
	$$('div.map').each(function(container) { new GoogleMap(container); });
	// create tabs:
	$$('ul.tabs').each(function(ul) {
		new Tabs(ul, {
			selectedClassName: 'selectedtab',
			contentSelector: '.tabcontent',
			useHash: true
		});
	});
	// open new-window links in a new window:
	$$('a[rel=external]').each(function(e) {
		e.addClassName('external').observe('click', function newWindow(event) {
			event.stop(); window.open(event.findElement('a').readAttribute('href'));
		});
	});
	// inputs with the classname focusclear are cleared on focus:
	$$('input.focusclear').each(function(input) { new FocusClear(input); });
	// submit (search/filter) form on each change:
	$$('form.changesubmit').each(function(form) {
		form.select('p.submit-buttons').invoke('hide');
		form.select('select').invoke('observe', 'change', function(event) {
			event.findElement('form').submit();
		});
	});
	// Create calendars
	$$('input.calendar').each(function(input) {
		var container = new Element('div').addClassName('calendar');
		// make sure we don't insert a div in a paragraph:
		if(input.up().tagName.toLowerCase() == 'p') {
			input.up('p').insert({after: container});
		} else {
			input.insert({before: container});
		}
		
		if(input.hasClassName('weekselect')) {
			new WeekSelectCalendar({
				container: container,
				targetInput: input,
				sourceFormat: 'yyyyMMdd', // default formats for announcements
				returnFormat: 'yyyyMMdd',
				onUpdate: function onUpdate(calendar) {
					calendar.element.up('form').submit();
				}
			});
		} else {
			new Calendar({
				container: container,
				targetInput: input
			});
		}
	});
});
