

TimeLine = new Class({
	years: [],
	markers: [],
	timespans: [],
		
	initialize: function(targetContainer, elements, options)
	{
		this.targetContainer = $(targetContainer);
		this.setOptions(options);
		this.timePoints = this.grabTimePoints(elements);
		this.calculateRange();
		this.draw();
		this.attachEvents();
	},

	options: {
		availableWidth: null,
		padding: 40
	},

	attachEvents: function() {
		window.addEvent('resize', this.draw.bind(this));
	},

	sort:function(elm1, elm2)
	{
		return(elm1.endDate.getTime() - elm2.endDate.getTime());
	},

	grabTimePoints:function(elements) {
		var output = [];
		for(i=0;i<elements.length; i++) {
			output.push(new PointInTime(elements[i], this, this.options));
		}
		output = output.sort(this.sort);

		output.each(function(point) {
			if(point.marker != false) { this.markers.push(point); }
			if(point.timespan != false) { this.timespans.push(point); }
		}.bind(this));
		return output;
	},

	calculateRange: function() {
		this.startDate = new Date(this.timePoints[0].startDate.getFullYear(), 0,1);	
		this.endDate = new Date(this.timePoints.getLast().endDate.getFullYear() +1 ,0,1);
		this.numberOfSteps = this.getMonthDifference(this.startDate, this.endDate);
	},

	getMonthDifference:function(date1, date2)
	{
		if (date1 > date2) return this.getMonthDifference(date2, date1);
		var number = 0;
		if (date2.getFullYear() > date1.getFullYear()) {
			number += ((date2.getFullYear() - date1.getFullYear() - 1) * 12);
		} else {
			return date2.getMonth() - date1.getMonth();
		}
		number += (date2.getMonth() > date1.getMonth()) ? (12 + date2.getMonth() - date1.getMonth()) : ((12 - date1.getMonth()) + date2.getMonth()) ;
		return number;
	},

	getPosition: function(date)
	{
		months = this.getMonthDifference(this.startDate, date);
		return(Math.round((this.options.availableWidth / this.numberOfSteps) * months));
	},	

	draw: function()
	{
		var start = this.startDate;	

		this.options.availableWidth = $(document.body).getSize().x - (this.options.padding * 2);
  
		if($(this.targetContainer)) $(this.targetContainer).set('html', '');
		
		this.line = new Element('DIV').addClass('line').setStyle('width', this.options.availableWidth);
		this.line.timeline = this;

		this.years = [ new YearMark(start.getFullYear(), this.line, {labelClassName:'year'}).setPosition(this.getPosition(start)) ];

		// loop through the years from start to end, drawing a marker for each.
		while(start.getFullYear() < this.endDate.getFullYear())
		{
			start = new Date(start.getFullYear() +1, 0, 1); // get next year
			this.years.push( new YearMark(start.getFullYear(), this.line, {labelClassName:'year'}).setPosition(this.getPosition(start)) ); // insert and setposition
		}
		var lastOptions = {couldOverlap: false };
		var previousDate = false;
		// draw each point in time
		for(i=0; i<this.timePoints.length; i++)
		{ 
			this.timePoints[i].draw(this.line, {couldOverlap: this.calculateOverlap(i) });
		}		
		this.line.injectInside(this.targetContainer);
	},

	// anything that's 2 months away from the previous date could possibly overlap. (hacky collision detection)
	calculateOverlap: function(timePointIndex) 
	{
		if (timePointIndex == 0) return false;
		return this.getMonthDifference(this.timePoints[timePointIndex-1].endDate, this.timePoints[timePointIndex].startDate) > 1;
	}

});



PointInTime = new Class({

	marker: false,
	timespan: false,

	initialize: function(dateTag, parent, options)
	{
		this.dateTag = dateTag;
		this.setOptions(options);
		this.parent = parent;
		var dates = dateTag.value.split('/');
		this.startDate = this.parseDate(dates[0]);
		this.endDate = (dates.length == 2) ? this.parseDate(dates[1]) : this.startDate;

	},

	parseDate: function(inputstring)
	{
		 var outdate = inputstring.split(/[-|/|\.]/);
		 return (outdate.length == 3) ? new Date(outdate[2], outdate[1] - 1, outdate[0], 1, 1, 0, 0) : false;
	},

	draw: function(line, extraOptions)
	{
		var start = this.parent.getPosition(this.startDate);
		var end = this.parent.getPosition(this.endDate);
		if(start == end) { 
			this.marker = new Marker(this.dateTag.name, line, {
					couldOverlap: extraOptions.couldOverlap, 
					position: start,
					events: this.options.markerEvents,
					dateTag: this.dateTag
				});
		}
		else
		{ 
			this.timespan = new TimeSpan(this.dateTag.name, line, {
				couldOverlap: extraOptions.couldOverlap,
				position: [start, end - start],
				events: this.options.timespanEvents,
				dateTag: this.dateTag
			});
		}
		$(this.dateTag).fireEvent('draw', this);

	}
});

TimelineDecorator = new Class({
	initialize:function(label, parent, options) {
		this.setOptions(options);
		this.parent = parent;
		this.element = new Element('DIV').addClass(this.options.className).injectInside(parent);
		this.label  = new Element('SPAN').addClass(this.options.labelClassName).injectInside(this.element);
		if(this.options.position) this.setPosition(this.options.position);
		this.dateTag = options.dateTag
		this.setLabel(label);

		return this;
	},

	addOptions: function(options)
	{
		this.label.set(options);
		return this;
	},
	setParent: function(timepoint)
	{
		this.label.parent = this.element.parent = timepoint;
		return this;
	},

	setPosition: function(value) {
		this.element.setStyle('left', value);
		return this;
	},

	setLabel: function(value) {
		if(typeof this.label != "undefined") {
		this.label.set('html', value);
		return this;
		}
		
	}

});

YearMark = new Class({
	Extends: TimelineDecorator,

	options: {
		className:'yearmark',
		labelClassName: 'label'
	}

});

Marker = new Class({
	Extends: TimelineDecorator,

	options: {
		className:'mark',
		labelClassName: 'label'
	},

	initialize:function(label, parent, options) {
		this.parent(label, parent, options);
		if(this.options.couldOverlap) {
			this.label.addClass('couldOverlap');
		}
		$H(options.events).each(function(func, evt) {
			 this.label.addEvent(evt, func.bindWithEvent(this)); 
		}.bind(this))
	}

});


TimeSpan = new Class({
	Extends: TimelineDecorator,

	options: {
		className:'timespan',
		labelClassName: 'label'
	},
	
	initialize:function(label, parent, options) {
		this.parent(label, parent, options);
		$H(options.events).each(function(func, evt) {
			 this.element.addEvent(evt, func.bindWithEvent(this)); 
		}.bind(this))
	},

	setPosition: function(left, width) {
		this.element.setStyle('left', left || arguments[0][0]);
		this.element.setStyle('width', width || arguments[0][1]);
		return this;
	}
});

cvMenu = new Class({
	initialize:function(elements, buttons, options) {
		this.setOptions(options);
		this.elements = elements
		
		this.buttons = buttons;
		this.opened = false;
		this.draw();
		return this;
	},

	hideAll: function()
	{
		try
		{
			if(this.opened && this.opened.effect && !this.opened.moving)
			{
				if(this.opened.getElement('.companyImage')) {
						this.opened.getElement('.companyImage').morph({opacity: 0});
				}
				this.opened.moving= true;
				this.opened.effect.setOptions({mode:'horizontal', onComplete: function(){ 
					this.opened.moving=false;
					this.drawNew();
				}.bind(this)}).slideOut();
			}
		}
		catch (E){ }
	},

	toggle: function(current){
		if($(current))
		{
				this.newElement = $(current).clone();
				this.newElement.setStyle('display','block');
				this.newElement.setAttribute('id', '');	
				if(this.newElement.getElement('.companyImage')) {
					this.newElement.getElement('.companyImage').setOpacity(0);
				}	
		}
		if(this.open && this.open.effect) this.open.effect.stop();
		if(this.opened) {this.hideAll(); } else this.drawNew();
		return this;
	},

	drawNew: function(newEl)
	{
		if(this.newElement && !this.opened.moving)
		{
			this.content.empty();
			this.opened = this.newElement.injectInside(this.content);
			this.opened.effect = new Fx.Slide(this.opened, {mode:'vertical', transition: 'sine:in',
				onComplete: function(){ 
					if(this.element.getElement('.companyImage')) {
						this.element.getElement('.companyImage').morph({opacity: 1});
					}
				}}).hide().slideIn();	
		}
	},

	draw:function()
	{
		this.content = new Element('DIV').addClass('slideContent').injectInside(document.body);
		this.buttons.addEvent('click', function(){ window.Menu.toggle(this.className);  return false; });
	}
});




cvMenu.implement(new Options, new Chain);
TimeLine.implement(new Options, new Events);
PointInTime.implement(new Options, new Events);
TimelineDecorator.implement(new Options, new Events);



window.addEvent('load', function(){

		window.TimeLine = new TimeLine($('timeline'), $$(".dateTag"), {
			yearEvents: {},
			dateTagEvents: {
				'draw' : function(tag) {

				}
			},
			markerEvents: {
				'mouseover': function() {
					this.label.set('morph', {duration: 200, transition: Fx.Transitions.Sine.easeOut});
					this.label.morph('.hoverLabel');
				},
				'mouseout': function() {
					this.label.morph('.normalLabel');
				},
				'click': function(event) {
					var el = $(this.dateTag);
					while (!$(el).hasClass('section') && !$(el).hasClass('jobInfo')) {	
						el = el.getParent();
					}
					window.Menu.toggle(el);				
				}
			},
			timespanEvents: {
				'mouseenter': function(evt) {
					if(!this.logoFloater) {
						this.logoFloater = new Element('div').addClass('floatingLogo').adopt(
								this.dateTag.getParent('.jobInfo').getFirst('.companyImage').clone()
							).injectInside(document.body);
						var parentPos = $(evt.target).getPosition()
						parentPos.y += 150;
						parentPos.x -= 60;
						this.logoFloater.setPosition(parentPos).hide().set('reveal', {mode:'vertical', duration:500});
					}
					this.logoFloater.reveal();
					this.element.set('morph', {duration: 700, transition: Fx.Transitions.Sine.easeOut});
					this.element.morph({backgroundColor: '#FFFFCC'});
				},
				'mouseleave': function() {
						if(this.logoFloater) this.logoFloater.dissolve();
						this.element.morph({backgroundColor: '#FFFFFF'});
				},
				'click': function(event) { 
					if(this.logoFloater) {
						this.logoFloater.nix();
						this.logoFloater = false;
					}
					var el = $(this.dateTag);
					while (!$(el).hasClass('section') && !$(el).hasClass('jobInfo')) {	
						el = el.getParent();
					}
					window.Menu.toggle(el);				
				}
			}
		});
		window.Menu = new cvMenu($$('.section'), $$('#navigation A')).toggle( (window.location.hash != '') ? window.location.hash.replace('#', '') : 'inleiding' );
});

