/*
 * Steuerung Legende
 */
(function($) {
	function handleClick(element) {
		var lastclick = -1, lastclickX = -1, lastclickY = -1;
		var timeoutId = -1;
		
		element.click(function(event) {
			event.preventDefault();
			
			if(Math.abs($.now() - lastclick) < 200) {
				clearTimeout(timeoutId);
				lastclick = -1;
				return element.trigger('lp_doubleclick');
			}
			else {
				timeoutId = setTimeout(function() {
					element.trigger('lp_singleclick', [lastclickX, lastclickY]);
					lastclick = -1, lastclickX = -1, lastclickY = -1;
				}, 200);
				lastclickX = event.pageX;
				lastclickY = event.pageY;
				lastclick = $.now();
			}
		});
	}
	
	$(document).ready(function() {
		$('.site a').mouseover(function(event) {
			$(this).addClass('selected')
		}).mouseleave(function(event) {
			$(this).removeClass('selected')
		}).bind('lp_singleclick', function(event, pageX, pageY){
			event.preventDefault();

			var toggle = $(this).parent('li').hasClass('deactivated') ? $("<a class='toggle activate'>Preisverlauf aktvieren</a>") : $("<a class='toggle deactivate'>Preisverlauf deaktvieren</a>");
			$("<div id='legendpopup'><a class='visit' href='" + $(this).attr('href') + "'>Zu " + $(this).parent('li').data('name') + "</a></div>").append(toggle).css({
				top:  /*event.*/pageY - 15,
				left: /*event.*/pageX - 15
			}).appendTo($(this).parent('li')).mouseleave(function() {
				$(this).remove();
			}).children('.toggle').click(function (event) {   	
				if($(this).hasClass('toggle')) {
					event.preventDefault();
	
					if($(this).hasClass('activate'))
						$(this).parents('li').removeClass('deactivated');
					else
						$(this).parents('li').addClass('deactivated');
	
					$('#plot_'+$(this).parents('.pbox').data('mode')).trigger('lp_repaint');
					$('#legendpopup').remove();
	        	}
	        });
		}).bind('lp_doubleclick', function(event) {
			$('#pbox_'+$(this).parents('.pbox').data('mode')+' .site a').each(function(key, site) {
				$(site).parents('li').addClass('deactivated');
			});
			$(this).parents('li').removeClass('deactivated');
			$('#plot_'+$(this).parents('.pbox').data('mode')).trigger('lp_repaint');
		}).each(function(key, element) {
			handleClick($(element));			
		});
	});
})(jQuery);

/*
 * Steuerung des Flot Graphen
 */
(function($) {
	// Übersetzungen für Datumsangaben
	var l10n_monthnamesshort = ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'];
	var l10n_monthnameslong  = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'];
	var l10n_days            = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'];
		
	// geteilte Plot-Information
	var _plotRange  = {buy: -1, sell: -1}
	var _plotOption = {buy: {}, sell: {}};
	var _plotHover  = {buy: -1, sell: -1};
		
	/** 
	 * grau eingefärbte Wochenenden
	 */
	function weekendAreas(axes) {
	    var markings = [];
	    var d = new Date(axes.xaxis.min);
	    
	    d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))
	    d.setUTCSeconds(0);
	    d.setUTCMinutes(0);
	    d.setUTCHours(0);
	    var i = d.getTime();
	    do {
	        markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } });
	        i += 7 * 24 * 60 * 60 * 1000;
	    } while (i < axes.xaxis.max);

	    return markings;
	}
		
	/**
	 * Euro-Werte auf Y-Achse
	 */
	function eurofyIt(val, axis) {
	    return val.toFixed(axis.tickDecimals).toString().replace('.', ',') + '¤';
	}
		
	/**
	 * paddet String links mit 0en um auf 2 Stellen zu kommen
	 */
	function leftpad(str) {
		if((str + '').length < 2) return leftpad('0'+str);
		return str;
	}
	
	/**
	 * returnt letztes Element in Array
	 */
	function lastElement(arr) {
		var el = arr.pop();
		arr.push(el);
		
		return el;
	}
	
	/**
	 * returnt erstees Element in Array
	 */
	function firstElement(arr) {
		var el = arr.shift();
		arr.unshift(el);
		
		return el;
	}
	
	/*
	 * erstellt Tooltip-Inhalt
	 */
	function tooltip(affialte, time, price) {
		var priceParts = (price + '').split('.');
		var formattedPrice = (priceParts.length == 1) ? priceParts[0]+',00' : ((priceParts[1].length == 2) ? priceParts[0]+','+priceParts[1] : priceParts[0]+','+priceParts[1]+'0');		
		var date = l10n_days[time.getUTCDay()] + ', ' + time.getUTCDate() + '. ' + l10n_monthnameslong[time.getUTCMonth()] + ' ' + time.getUTCFullYear() + ' ' + leftpad(time.getUTCHours()) + ':' + leftpad(time.getUTCMinutes());
		return "<div id='tooltip'><strong>" + formattedPrice + " ¤/Mrd</strong><br />" + date + "<br /><div class='siteslist'><span class='sitecolorbox' style='background-color: " + $('li[data-affialteid='+affialte+']').data('color') + ";'></span> " + $('li[data-affialteid='+affialte+']').data('name') + "</div></div>";
	}

	/**
	 * malt den Graphen neu ohne ihn neu zu initialisieren
	 */
	function repaintGraph(element, affialtes, mode) {
		// Zusammenstellung Datenbereiche
		var plots = [];
		plots.push({color: '#000000', data: data['avg'][mode]});
		affialtes.each(function(devnull, affialte) {
			var affialteid = $(affialte).data('affialteid');
			var points = affialteid == _plotHover[mode];
			plots.push({lines: {show: true, steps: true}, points: {show: points}, color: $(affialte).data('color'), data: data[mode][affialteid]});
		});
		
		// X-Range bestimmen
		var plotSelection = _plotOption[mode];
		if(_plotRange[mode] == -1 && $.isEmptyObject(plotSelection)) {
			plotSelection = {xaxis: {min: firstElement(plots[0].data)[0], max: lastElement(plots[0].data)[0]}};	
		}
		if(_plotRange[mode] > 0 && $.isEmptyObject(plotSelection))
			plotSelection = {xaxis: {min: lastElement(plots[0].data)[0] - _plotRange[mode] * 1000, max: lastElement(plots[0].data)[0]}};
		
		// Min-Max finden
		var min = Number.MAX_VALUE, max = Number.MIN_VALUE;
		for(var i in plots) {
			var before = null, first = null, last = null, after = null;
			
			for(var j in plots[i].data) {
				// Einträge davor ignorieren
				if(plotSelection.xaxis != null && plots[i].data[j][0] < plotSelection.xaxis.min) {
					before = plots[i].data[j];
					continue;
				}
				
				// Einträge danach ignorieren
				if(plotSelection.xaxis != null && plots[i].data[j][0] > plotSelection.xaxis.max) {
					if(after == null) after = plots[i].data[j];
					break;
				}
				
				if(first == null) first = plots[i].data[j];
				last = plots[i].data[j];
				
				min = Math.min(min, plots[i].data[j][1]);
				max = Math.max(max, plots[i].data[j][1]);
			}
			
			// 1. Punkt vor Range und erster Punkt in Range
			if(before != null && first != null && plotSelection.xaxis != null) {
				min = Math.min(min, lastElement(before));
				max = Math.max(max, lastElement(before));
			}
			// 2. Punkt in Range und erster Punkt nach Range
			if(last != null && after != null && plotSelection.xaxis != null) {
				min = Math.min(min, lastElement(after));
				max = Math.max(max, lastElement(after));
			}
			// 3. Punkt vor linker Range, Punkt nach rechter Range und keiner mittendrin
			if(before != null && last == null && after != null && plotSelection.xaxis != null) {
				min = Math.min(min, lastElement(before), lastElement(after));
				max = Math.max(max, lastElement(before), lastElement(after));
			}
			
		}
		min = (min % 5 == 0) ? min - 1 * 5 : (Math.floor(min/5) - 1) * 5;
		max = (max % 5 == 0) ? max + 1 * 5 : (Math.ceil (max/5) + 1) * 5;

		// Plotoptionen zusammenstellen
		var color = (mode == 'buy' ? '#FFDCDC' : '#E0F8D5');
		var options = $.extend(true, {}, {
			lines: {show: true},
			grid: { hoverable: true, backgroundColor: {colors: ['#FFFFFF', color] }, markings: weekendAreas},
			xaxis: {mode: 'time', monthnames: l10n_monthnamesshort},
			yaxis: {tickDecimals: 2, tickFormatter: eurofyIt, min: min, max: max},
			selection: { mode: 'x'}
		}, plotSelection);
		
		// Plot erzeugen
		$.plot(element, plots.reverse(), options);			
	}
		
	/**
	 * Hauptfunktion zur Plotanzeige (initialisiert und malt einmal)
	 */
	function showGraph(element, affialtes, mode) {
		// initiale Plot-Range eintragen
		var rangetype = $('.zeitraumdiv[data-type='+mode+'] .zeitraum.active').data('range');
		_plotRange[mode] = rangetype;
		
		// Graph malen
		repaintGraph(element, affialtes, mode);
			
		// auf Plot hover reagieren
		var tooltipActive = false;
		element.bind("plothover", function (event, pos, item) {
			// einblenden
			if(item != null) {
				$("#tooltip").remove();
				var affialte = $('li[data-color='+item.series.color+']').data('affialteid');
				$(tooltip(affialte, new Date(item.datapoint[0]), item.datapoint[1])).css({
					top: item.pageY + 15,
					left: item.pageX + 15
				}).appendTo("body");
					
				tooltipActive = true;
			}
			// ausblenden 
			else if(tooltipActive){
				$("#tooltip").remove();
				tooltipActive = false;
			}
		});
			
		// auf Plot zooming reagieren
		element.bind('plotselected', function (event, ranges) {
			_plotOption[mode] = {xaxis: {min: ranges.xaxis.from, max: ranges.xaxis.to}};
			repaintGraph(element, $('#pbox_'+mode+' li.site:not(.deactivated):not(.invisible)'), mode);
			$('.rview[data-mode='+mode+']').trigger('lp_resettable', [true]);
		});
			
		// auf Plot-Zoom-Reset reagieren
		element.bind('lp_zoomreset', function (event) {
			_plotOption[mode] = {};
			repaintGraph(element, $('#pbox_'+mode+' li.site:not(.deactivated):not(.invisible)'), mode);
		});
		
		// auf Plot-Repaint-Request reagieren
		element.bind('lp_repaint', function (event) {
			repaintGraph(element, $('#pbox_'+mode+' li.site:not(.deactivated):not(.invisible)'), mode);
		});
		
		// auf Plot-Range-Change reagieren
		$('.zeitraumdiv[data-type='+mode+'] .zeitraum').click(function (event) {
			event.preventDefault();
			
			_plotRange[mode] = $(this).data('range');
			_plotOption[mode] = {};
			repaintGraph(element, $('#pbox_'+mode+' li.site:not(.deactivated):not(.invisible)'), mode);
			$('.rview[data-mode='+mode+']').trigger('lp_resettable', [false]);
			
			$('.zeitraumdiv[data-type='+mode+'] .zeitraum').removeClass('active');
			$(this).addClass('active');
		});
	}
	
	/**
	 * fügt aktuelle Zeitpunkte mit unveränderten Werten in Array
	 * (Losepreisdaten werden nur bei Änderung aktualisiert)
	 * (machen wir das nicht, ist die x-Achse rechts nicht die Echtzeit)
	 */
	function addNowDatapoints() {
		function calcActualValue(arr) {
			var last = arr.pop();
			arr.push(last)

			return [new Date().getTime(), last[1]];
		}
		
		// behebe alle Daten
		data.avg.buy.push (calcActualValue(data.avg.buy));
		data.avg.sell.push(calcActualValue(data.avg.sell));
		for(i in data.buy)
			data.buy[i].push( calcActualValue(data.buy[i]));
		for(i in data.sell)
			data.sell[i].push(calcActualValue(data.sell[i]));
	}
	
	/**
	 * behebt Zeitzonen-Probleme
	 */
	function fixDatapointTimezones() {
		/**
		 * berechnet Faktor in alle Elemente ein
		 */
		function fixArray(arr, offset) {
			for(i in arr)
				arr[i][0] += offset;
		}
		
		// berechne Faktor zum Addieren auf Zeitstempel (flot interpretiert Daten als UTC)
		// Idee: berechne aktuellen Zeitzonen-Offset und addiere ihn
		var addFactor = -1 * new Date().getTimezoneOffset() * 60 * 1000;

		// behebe alle Daten
		fixArray(data.avg.buy,  2 * 60 * 60 * 1000);
		fixArray(data.avg.sell, addFactor);
		for(i in data.buy)
			fixArray(data.buy[i],  addFactor);
		for(i in data.sell)
			fixArray(data.sell[i], addFactor);
	}
	
	$(document).ready(function() {
		addNowDatapoints();
		fixDatapointTimezones();
		showGraph($('#plot_buy'),  $('#pbox_buy  li.site:not(.deactivated):not(.invisible)'), 'buy');
		showGraph($('#plot_sell'), $('#pbox_sell li.site:not(.deactivated):not(.invisible)'), 'sell');
	});
})(jQuery);

/**
 * Buttons
 */
(function($) {
	/**
	 * Buttonlogik
	 */
	function handleResetButton(element, mode) {
		element.click(function(event) {
			element.prop('disabled', true);
			$('#plot_'+mode).trigger('lp_zoomreset');
		});
		
		element.bind('lp_resettable', function(event, mode) {
			element.prop('disabled', !mode);
		});
	}
	
	$(document).ready(function() {
		handleResetButton($('.rview[data-mode=buy] '), 'buy');
		handleResetButton($('.rview[data-mode=sell]'), 'sell');		
	});
})(jQuery);
