// to do:
// auto-schrittweite +
// exponentialfunktionen +
// komplexere exp-funktionen -> exp ermitteln
// zahlen mit . zulassen
// zoom-funktion mit mausrad
// einfache ableitungen
// potenzgesetze -> für variablen
// fehler negative zahlen +
// funktionenschar +
// e-funktion
// trigonometrische
// komische Rucker beim hoch- und runterbewegen
// nicht alle Werte neuberechnen beim bewegen


// *********************************************
// ++ mflot - Funktionen mit mflot darstellen ++
// *********************************************
// Autor: Patrick Fischer
// Datum: 04.02.2008 Version 0.5
// Seite: http://www.ajaxschmiede.de
// *********************************************

function autoScale(xMax, xMin, pWidth) {
	return dezRound(4 * (xMax-xMin) / pWidth, 6);
}


$(document).ready( function () {
	
	// automatische Schrittweise an/aus
	$("#range input:last").click( function () {
		if ($(this).attr("checked")) {
			$("#range input:eq(2)").attr("disabled", "disabled");
		} else {
			$("#range input:eq(2)").removeAttr("disabled");
		}
	});

	// Kurvenschar an/aus
	$("#array input:last").click( function () {
		if ($(this).attr("checked")) {
			$("#array input").not(":last").attr("disabled", "disabled");
		} else {
			$("#array input").not(":last").removeAttr("disabled");
		}
	});

	// fügt Verschiebefunktionen hinzu
	$("#graph .scroll:eq(0)").click( function () {

		// Parameter für Anzeigebereich
		yMin			= Number($("#view input:eq(0)").attr("value"));
		yMax			= Number($("#view input:eq(1)").attr("value"));
		yDif			= (yMax - yMin) / 10;

		// Parameter für Anzeigebereich neu setzen		
		$("#view input:eq(0)").attr("value", yMin + yDif);
		$("#view input:eq(1)").attr("value", yMax + yDif);

		calculate();
	});

	// fügt Verschiebefunktionen hinzu
	$("#graph .scroll:eq(2)").click( function () {

		// Parameter für Anzeigebereich
		yMin			= Number($("#view input:eq(0)").attr("value"));
		yMax			= Number($("#view input:eq(1)").attr("value"));
		yDif			= (yMax - yMin) / 10;

		// Parameter für Anzeigebereich neu setzen		
		$("#view input:eq(0)").attr("value", yMin - yDif);
		$("#view input:eq(1)").attr("value", yMax - yDif);

		calculate();
	});

	// fügt Verschiebefunktionen hinzu
	$("#graph .scroll:eq(1)").click( function () {

		// er-/enthält Parameter zum Berechnen und Zeichnen
		xMin			= Number($("#range input:eq(0)").attr("value"));
		xMax			= Number($("#range input:eq(1)").attr("value"));
		xDif			= (xMax - xMin) / 10;

		// Parameter für Anzeigebereich neu setzen		
		$("#range input:eq(0)").attr("value", xMin + xDif);
		$("#range input:eq(1)").attr("value", xMax + xDif);

		calculate();
	});

	// fügt Verschiebefunktionen hinzu
	$("#graph .scroll:eq(3)").click( function () {

		// er-/enthält Parameter zum Berechnen und Zeichnen
		xMin			= Number($("#range input:eq(0)").attr("value"));
		xMax			= Number($("#range input:eq(1)").attr("value"));
		xDif			= (xMax - xMin) / 10;

		// Parameter für Anzeigebereich neu setzen		
		$("#range input:eq(0)").attr("value", xMin - xDif);
		$("#range input:eq(1)").attr("value", xMax - xDif);

		calculate();
	});

	// Mausevent fürs Überfahren der Buttons
	$("#graph .scroll").hover( function () {
		$(this).css("opacity", "1");
		$(this).css("filter", "opacity=100");
	}, function () {
		$(this).css("opacity", "0.3");
		$(this).css("filter", "opacity=30");
	});


	// fügt dem button ein event zu
	$("#calculate").click( function () {
		calculate();
	});

	// Funktion zum Berechnen und Anzeigen
	function calculate() {

		// er-/enthält die Funktion
		funktion		= $("#function input:first").attr("value");

		// er-/enthält Parameter zum Berechnen und Zeichnen
		xMin			= Number($("#range input:eq(0)").attr("value"));
		xMax			= Number($("#range input:eq(1)").attr("value"));
		schrittweite	= Number($("#range input:eq(2)").attr("value"));

		// Parameter für Anzeigebereich
		yMin			= Number($("#view input:eq(0)").attr("value"));
		yMax			= Number($("#view input:eq(1)").attr("value"));
		pWidth			= Number($("#view input:eq(2)").attr("value"));
		pHeight			= Number($("#view input:eq(3)").attr("value"));

		// automatische Schrittweite
		if ($("#range input:eq(3)").attr("checked")) {
			schrittweite = autoScale(xMax, xMin, pWidth);
			$("#range input:eq(2)").attr("value", schrittweite)
		}

		// setzt Größe des Ausgabefensters
		$("#graph div:first").css({width: pWidth + "px", height: pHeight + "px"});

		// Punkte zum Zeichnen
		var1 = [];

		// Ersetzungen
		funktion = funktion.replace(/[\s]+/g, "");
		funktion = funktion.replace(/,/g, ".");
		funktion = funktion.replace(/²/g, "[2]");
		funktion = funktion.replace(/³/g, "[3]");

		// fügt Multiplikationszeichen vor Variablen und zwischen Variablen ein
		while ( var2 = /([0-9a-zA-Z]+)([a-zA-Z])/g.exec ( funktion ) ) {
			// neue RegExp
			var var3 = new RegExp ( var2[0] );
			//alert(var2);
			// fügt Multiplikationszeichen ein
			funktion = funktion.replace(var3, var2[1] + "*" + var2[2]);
			//alert(funktion);
		}

		// fügt Multiplikationszeichen vor öffnenden Klammern ein
		while ( var2 = /([a-zA-Z0-9\)\]])\(/g.exec ( funktion ) ) {
			//alert(var2);
			// neue RegExp
			var var3 = new RegExp ( var2[1] + "\\(" );
			//alert(var3);
			// fügt Multiplikationszeichen ein
			funktion = funktion.replace(var3, var2[1] + "*(");
			//alert(funktion);
		}

		// Potenzgesetz [x][y] = [x*y]
		while ( var2 = /\[([0-9]+[\.\,]?[0-9]*)\]\[([0-9]+[\.]?[0-9]*)\]/g.exec ( funktion ) ) {
			//alert(var2);
			// neue RegExp
			var var3 = new RegExp ( "\\[" + var2[1] + "\\]" + "\\[" + var2[2] + "\\]" );
			// ersetzen
			funktion = funktion.replace(var3, "[" + var2[1] * var2[2] + "]");
			//alert(funktion);
		}

		// ersetzt Potenzschreibweise
		while ( var2 = /([0-9]+[\.]?[0-9]*|[a-zA-Z])\[([0-9]+[\.]?[0-9]*|[a-zA-Z])\]/g.exec ( funktion ) ) {
			//alert(var2);
			// neue RegExp
			var var3 = new RegExp ( var2[1] + "\\[" + var2[2] + "\\]" );
			// ersetzen
			funktion = funktion.replace(var3, "Math.pow(" + var2[1] + ", " +  var2[2] + ")");
			//alert(funktion);
		}

		// ersetzt Potenzschreibweise - 2. Teil - mit Klammern		
		while ( var2 = /([\)]+)\[([0-9]+[\.]?[0-9]*|[a-zA-Z])\]/g.exec ( funktion ) ) {
			// ermittelt Position des Treffers
			var pos = funktion.search( /([\)]+)\[([0-9]+[\.]?[0-9]*|[a-zA-Z])\]/ );
			// Anzahl der schließenden Klammern
			var count = var2[1].match( /\)/g );
			count = count.length;
			pos += count-1;
			// sucht vor schließenden Klammern nach weiteren Klammern - Abbruch wenn öffnende Klammern gleich schließende oder Anfang
			for ( var i = pos-count; i >= 0; i-- )
			{
				if ( funktion.substr(i, 1) == "(" ) count--;
				if ( funktion.substr(i, 1) == ")" ) count++;

				if ( count == 0) break; 
			}
			// zu potenziernde Funktion
			var subfunc = funktion.substring( i+1, pos );
			// Ersetzungen
			var2[1] = funktion.substring( i, pos+1 ).replace(/\)/g, "\\)");
			var2[1] = var2[1].replace(/\(/g, "\\(");
			var2[1] = var2[1].replace(/\+/g, "\\+");
			var2[1] = var2[1].replace(/\*/g, "\\*");
			var2[1] = var2[1].replace(/\//g, "\\/");
			// neue RegExp
			var var3 = new RegExp ( var2[1] + "\\[" + var2[2] + "\\]" );
			// ersetzen
			funktion = funktion.replace(var3, "Math.pow(" + subfunc + ", " +  var2[2] + ")" );
			//alert(funktion);
		}
		
		// zeigt Funktion an
		$("#func").html(funktion);

		// wenn Kurvenschar und a in Funktion vorhanden
		if ( $("#view input:last").attr("checked") ) {
			// Funktion(en)-Array bestehend aus Objekten mit Achsen
			data = [
				{ color: "rgb(120, 120, 120)", data: [[xMin, 0], [xMax, 0]], shadowSize: 0 },
				{ color: "rgb(120, 120, 120)", data: [[0, yMin], [0, yMax]], shadowSize: 0 }
			];
		} else {
			// leeres Funktion(en)-Array bestehend aus Objekten
			data = [];
		}

		// wenn Kurvenschar und a in Funktion vorhanden
		if ( !$("#array input:last").attr("checked") && funktion.match(/z/g) ) {
			zMin			= Number($("#array input:eq(0)").attr("value"));
			zMax			= Number($("#array input:eq(1)").attr("value"));
			zSchrittweite	= Number($("#array input:eq(2)").attr("value"));

			var k = -1;

			// Schleife zum Ersetzen der Variablen z durch Werte
			// dezRound behebt Berechnungsfehler bei Kommazahlen im Zusammenhang mit Binärzahlen
			for ( var j = zMin; j <= zMax; j = dezRound(j + zSchrittweite, 5) ) {
				var1[++k] = [];
				// Schleife zum Ersetzen der Variablen x durch Werte
				// dezRound behebt Berechnungsfehler bei Kommazahlen im Zusammenhang mit Binärzahlen
				for ( var i = xMin; i <= xMax; i = dezRound(i + schrittweite, 5) ) {
					// ersetzt z mit Zahl
					ausgabe = funktion.replace(/z/gi, j);
					// ersetzt x mit Zahl
					ausgabe = ausgabe.replace(/x/gi, i);
					// ersetzt -- durch +
					ausgabe = ausgabe.replace(/--/gi, "+");
					//alert(ausgabe);
					// hängt berechneten Punkt an
					var1[k].push([i, dezRound(eval(ausgabe), 9)]);
				}

				// hängt Funktions-Objekt an
				data.push( { color: k, data: var1[k] } );
			}
		} else {
			// Schleife zum Ersetzen der Variablen x durch Werte
			// dezRound behebt Berechnungsfehler bei Kommazahlen im Zusammenhang mit Binärzahlen
			for ( var i = xMin; i <= xMax; i = dezRound(i + schrittweite, 5) ) {
				// ersetzt x mit Zahl
				ausgabe = funktion.replace(/x/gi, i);
				// ersetzt -- durch +
				ausgabe = ausgabe.replace(/--/gi, "+");
				//alert(ausgabe);
				// hängt berechneten Punkt an
				var1.push([i, dezRound(eval(ausgabe), 9)]);
			}

			// hängt Funktions-Objekt an
			data.push( { color: "rgb(0, 0, 0)", data: var1 } );
		}

		// zeichnet Graph
		$.plot($("#graph div:first"), data, {
		xaxis: {
			min: xMin,
			max: xMax
		},
		yaxis: {
			min: yMin,
			max: yMax
		}
		});

		// machts Scrollbuttons sichtbar
		$("#graph .scroll").css("display", "block");

		// positioniert Scrollbuttons
		$("#graph .scroll:eq(0)").css("left", (pWidth-100)/2+10 + "px");
		$("#graph .scroll:eq(2)").css("left", (pWidth-100)/2+10 + "px");
		$("#graph .scroll:eq(1)").css("top", (pHeight-20)/2-11 + "px");
		$("#graph .scroll:eq(1)").css("left", pWidth-107 + "px");
		$("#graph .scroll:eq(3)").css("top", (pHeight-20)/2-11 + "px");		
	};
});
