///////////////////////////////////////////////////////////////////////////
///
/// Projekt: web to date Pro Plugin web 2.0 Timeline
/// Autor: Volker Sauer, (C) 2005, 2006, 2007, 2008
/// etor Softwareentwicklung e.K.
/// Bottroper Str. 19, 45899 Gelsenkirchen, sauer@etor.de
///
/// Datei: timeline.js
/// Art: Javascript Klassen
/// Beschreibung: Klassen für die Anzeige des Zeitstrahls
/// CCML-Parsing: nein
///
////////////////////////////////////////////////////////////////////////////
///
/// Letzte Änderungen:
/// 25.02.2009: Popoup und Corsor bei Ereignissen ohne Bescheibung abgeschaltet
///
////////////////////////////////////////////////////////////////////////////
///<25.02.2009/1.0.1/>

// Konstanten
var BUTTON_SIZE = 20;
var BUTTON_PADDING = 4;
var CONTAINER_HEIGHT = 75;
var CONTAINER_WIDTH = 240;
var CONTAINER_PADDING = 6;
var IMG_SIZE = 55;
var POPUP_SIZE = 402;

// Breitenregelung, Maximalwerte für
// Tagesdifferenz erster und letzter Tag geteilt durch
// berechnete Mindesttagesabstand zwischen zwei Spalten
// mal eingestellter Faktor
// MAX_BASE + Faktor * MAX_ADD
var MAX_BASE = 100;
var MAX_ADD = 15;

// Klasse Zeitleiste
var Timeline = Class.create({

	// Konstruktor
	initialize: function(width, height, scale) {
		this.scale = scale;
		this.width = width
		this.height = height;
		this.events = new Array();
		this.h = Math.floor((this.height - (BUTTON_SIZE * 2) - CONTAINER_PADDING) / CONTAINER_HEIGHT);
		this.y = -1;
		$('timeline').absolutize().setStyle({height: (this.height - BUTTON_SIZE - BUTTON_PADDING) + 'px'}).observe('mousedown', this.popdown.bind(this));
		new Draggable('timeline', {
			constraint: 'horizontal',
			snap: this.snap.bind(this),
			starteffect: null,
			endeffect: null
		});
		$('popup').observe('click', this.popdown.bind(this)).absolutize().setStyle({
			width: (POPUP_SIZE - 2 * CONTAINER_PADDING) + 'px',
			height: (POPUP_SIZE - 2 * CONTAINER_PADDING) + 'px',
			left: ((this.width - POPUP_SIZE) / 2) + 'px',
			top: ((this.height - POPUP_SIZE - 2 * CONTAINER_PADDING - BUTTON_SIZE - BUTTON_PADDING) / 2) + 'px',
			padding: CONTAINER_PADDING + 'px'
		});
		$('text').setStyle({paddingBottom: BUTTON_PADDING + 'px'});
		this.pop = null;
	},

	// Berechnung erlaubter Werte fürs verschieben
	snap: function(x, y, d) {
		x = Math.max(x, this.coords.last());
		x = Math.min(x, this.coords.first());
		this.slider.setValue(- x);
		return [x, y];
	},

	// Element zur Zeitleiste hinzufügen
	add: function(anevent) {
		this.events.push(anevent);
	},

	// Zeitlsiet generieren, Elemente anzeigen
	generate: function() {
		// Größenangaben setzen
		$$('.img').each(function(element) { element.setStyle({
			width: IMG_SIZE + 'px'
		})});
		$('img').setStyle({
			left: CONTAINER_PADDING + 'px'
		});
		$$('.info').each(function(element) { element.setStyle({
			width: (CONTAINER_WIDTH - IMG_SIZE - CONTAINER_PADDING) + 'px',
			height: + (CONTAINER_HEIGHT - CONTAINER_PADDING) + 'px',
			marginLeft: IMG_SIZE + 'px'
		})});
		$('text').setStyle({
			marginLeft: IMG_SIZE + 'px'
		});
		$$('.container').each(function(element) { element.setStyle({
			width: (CONTAINER_WIDTH - CONTAINER_PADDING) + 'px'
		})});

		// Unterschiede ausrechnen
		this.dates = new Array();
		this.events.each(function (element) {
			timeline.dates.push(element.index);
		});

		this.first = this.dates[0];

		this.last = this.dates[this.dates.length - 1];
		this.difference = this.last - this.first;
		if (this.dates.length > this.h)
			for (var i = this.h; i < this.dates.length; i++)
				this.difference = Math.min(this.dates[i] - this.dates[i - this.h], this.difference);

		var width = (this.last - this.first) / this.difference * this.scale;
		if (width > MAX_BASE + this.scale * MAX_ADD)
			this.scale = (MAX_BASE + this.scale * MAX_ADD) * this.difference / (this.last - this.first);

		var pixel_difference = 365 / this.difference * CONTAINER_WIDTH * this.scale + CONTAINER_PADDING;

		// Platzieren
		this.coords = new Array();
		lastxpos = new Array();
		for (var i = 0; i < this.h; i++)
			lastxpos[i] = -1000;

		this.events.each(function (element) {
			$(element.id).absolutize();

			var xpos = (element.index - this.first) / this.difference * CONTAINER_WIDTH * this.scale + CONTAINER_PADDING;
			var yi = this.ypos();

			if (xpos < lastxpos[yi] + CONTAINER_WIDTH + CONTAINER_PADDING)
				xpos = lastxpos[yi] + CONTAINER_WIDTH + CONTAINER_PADDING;

			lastxpos[yi] = xpos;

			$(element.id).setStyle({
				top: (yi * CONTAINER_HEIGHT + CONTAINER_PADDING) + 'px',
				left: xpos + 'px',
				cursor: (element.text ? 'pointer' : 'default')
			});

			var q = 1 - (this.last - element.index) / (this.last - this.first);
			var d = (this.width - CONTAINER_WIDTH - CONTAINER_PADDING) / CONTAINER_WIDTH * this.difference * q;
			var x = (- element.index + this.first) / this.difference * CONTAINER_WIDTH * this.scale +
				d / this.difference * CONTAINER_WIDTH;
			if (x > 0)
				x = 0;
			this.coords.push(Math.floor(x));
		}, this);

		// Legende
		var w = 0;
		var year_x = -300;
		var last_x = -200;

		for (var t = this.first - this.difference; t <= this.last + (this.difference * 2); t++) {
			var d = new Date();
			d.setTime(t * 1000 * 86400);

			// Beschriftung Jahreszahlen
			if (d.getDate() == 1 && !d.getMonth()) {
				year_x = (t - this.first) / this.difference * CONTAINER_WIDTH * this.scale + CONTAINER_PADDING;
				if (year_x > last_x + 150) {
					var div = new Element('div', {'class': 'year'}).update(d.getFullYear());
					div.absolutize().setStyle({
						top: (this.height - (BUTTON_SIZE * 2.5)) + 'px',
						left: (year_x - 22 + IMG_SIZE) + 'px'
					});
					$('timeline').insert(div);
					last_x = year_x;
				}

				// Überspringen von Tagen
				if (pixel_difference < 200)
					t += 360;

			// Beschriftung Monatszahlen
			} else if (d.getDate() == 1) {
				if (
					pixel_difference >= 250 &&
					(pixel_difference < 400 && d.getMonth() == 6 ||
					pixel_difference >= 400 && pixel_difference < 700 && (d.getMonth() == 3 || d.getMonth() == 6 || d.getMonth() == 9) ||
					pixel_difference >= 700 && pixel_difference < 1000 && (d.getMonth() +1) % 2 ||
					pixel_difference >= 1000)) {

					var month_x = (t - this.first) / this.difference * CONTAINER_WIDTH * this.scale;
					var div = new Element('div', {'class': 'month'}).update((d.getMonth() < 9 ? '0' : '') + (d.getMonth() + 1));
					div.absolutize().setStyle({
						top: (this.height -  (BUTTON_SIZE * 2.3)) + 'px',
						left: (month_x - 10 + IMG_SIZE) + 'px'
					});
					$('timeline').insert(div);
				}
			}
		}

		// Knöpfe
		$('tostart').absolutize().setStyle({
			top: (this.height - BUTTON_SIZE - BUTTON_PADDING) + 'px',
			left: BUTTON_PADDING + 'px'
		}).observe('click', this.tostart.bind(this));
		$('prev').absolutize().setStyle({
			top: (this.height - BUTTON_SIZE - BUTTON_PADDING) + 'px',
			left: (BUTTON_SIZE + 2 * BUTTON_PADDING) + 'px'
		}).observe('click', this.prev.bind(this));
		$('next').absolutize().setStyle({
			top: (this.height - BUTTON_SIZE - BUTTON_PADDING) + 'px',
			left: (this.width - 2 * BUTTON_SIZE - 2 * BUTTON_PADDING) + 'px'
		}).observe('click', this.next.bind(this));
		$('toend').absolutize().setStyle({
			top: (this.height - BUTTON_SIZE - BUTTON_PADDING) + 'px',
			left: (this.width - BUTTON_SIZE - BUTTON_PADDING) + 'px'
		}).observe('click', this.toend.bind(this));
		$$('.button').each(function(element) {
			element.setStyle({
				width: BUTTON_SIZE + 'px',
				height: BUTTON_SIZE + 'px'
			})
		});

		// Schieberegler
		var track_length = this.width - 4 * BUTTON_SIZE - 6 * BUTTON_PADDING;
		$('track').absolutize().setStyle({
			top: (this.height - BUTTON_SIZE - BUTTON_PADDING) + 'px',
			width: track_length + 'px',
			left: (2 * BUTTON_SIZE + 3 * BUTTON_PADDING) + 'px',
			height: BUTTON_SIZE + 'px'
		});
		var complete_width = (this.last - this.first) / this.difference * CONTAINER_WIDTH * this.scale + CONTAINER_WIDTH + 2 * CONTAINER_PADDING;

		if (complete_width < this.width)
			complete_width = this.width;

		w = this.width * this.width / complete_width * (this.width - 4 * BUTTON_SIZE - 6 * BUTTON_PADDING) / this.width;
		$('slider').setStyle({
			width: w + 'px',
			height: BUTTON_SIZE + 'px'
		});

		var last = this.coords.last() ? - this.coords.last() : 0;
		if (this.coords.last())
			this.slider = new Control.Slider($('track').down(), 'track', {
				range: $R(0, - this.coords.last()),
				increment: Math.floor(- this.coords.last() / track_length),
				onSlide: this.slide.bind(this),
				onChange: this.slide.bind(this)
			});

		w = (this.last - this.first) / this.difference * CONTAINER_WIDTH * this.scale + CONTAINER_WIDTH + 2 * CONTAINER_PADDING;
		$('timeline').setStyle({width:  w + 'px'});
	},

	// Auschnitt verschieben
	move: function(x) {
		this.popdown();
		new Effect.Move('timeline', {
			x: x,
			mode: 'absolute',
			transition: Effect.Transitions.sinoidal
		});
		this.slider.setValue(- x);
	},

	// An den Anfang schieben
	tostart: function() {
		this.move(this.coords.first());
	},

	// Zum vorherigen Ereignis schieben
	prev: function() {
		for (var i = this.coords.length - 1; i >= 0; i--)
			if ($('timeline').offsetLeft < this.coords[i]) {
				this.move(this.coords[i]);
				break;
			}
	},

	// Zum nächsten Ereignis schieben
	next: function() {
		for (var i = 0; i < this.coords.length; i++)
			if ($('timeline').offsetLeft > this.coords[i]) {
				this.move(this.coords[i]);
				break;
			}
	},

	// An das Ende schieben
	toend: function() {
		this.move(this.coords.last());
	},

	// Zeitleiste verschieben
	slide: function(value) {
		this.popdown();
		$('timeline').setStyle({left: - value + 'px'});
	},

	// Kaskadierung berechnen
	ypos: function() {
		this.y++;
		if (this.y == this.h)
			this.y = 0;
		return this.y;
	},

	// Popup öffnen
	popup: function(event) {
		event.stop();
		for (var i = 0; i < timeline.events.length; i++) {
			if (event.element().descendantOf($(timeline.events[i].id)) || event.element() == $(timeline.events[i].id))
				break;
		}
		var e = timeline.events[i];
		if (e.text) {
			if (e.picture)
				$('popup').down(1).show().src = e.picture;
			else
				$('popup').down(1).hide();
			$('popup').down().next().update('<h2>' + e.datetext + '<br />' + e.caption + '</h2>' + e.text);
			$('popup').show();
			this.pop = true;
		}
	},

	// Popup schliessen
	popdown: function() {
		if (this.pop)
			$('popup').fade({duration: 0.5});
		this.pop = false;
	}
});

// Klasse Ereignis
var Anevent = Class.create({
	initialize: function(day, month, year, caption, desc, text, picture) {
		if (month == 0) {
			month = 1;
			day = 1;
			this.datetext = year;
		} else
			this.datetext = (day < 10 ? '0' : '') + day + '.' + (month < 10 ? '0' : '') + month + '.' + year;

		this.date = new Date(year, month - 1, day);
		this.index = Math.floor(this.date.getTime() / 1000 / 86400);
		this.caption = caption;
		this.desc = desc,
		this.text = text;
		this.picture = picture;
		$('timeline').insert((new Template($('template').innerHTML)).evaluate({
			caption: this.caption,
			desc: this.desc,
			datetext: this.datetext
		}));
		this.id = $('timeline').childElements().last().identify();
		if (this.picture)
			$(this.id).down(1).show().src = this.picture;
		$(this.id).observe('mousedown', timeline.popup.bind(timeline));
	}
});

