/*	chords.js
	copyleft Tancrède Bastié 2004-2008

requires:
	dom.js
	gauge.js
	guitar_neck.js
	keyboard.js

index:
	Chords()
*/

function Chords(notBass, notLeftHanded) {

	var guitarNeck;
	var marksGauge;
	var noteKeyboard;
	var chordBase;
	var rootNode;
	var nameNode;

	addLoadEvent(
		function() {
			guitarNeck = new GuitarNeck(notBass, notLeftHanded, "Quel est cet accord ?");
			guitarNeck.addFretRange("fretRange", chords.makeQuestion);
			guitarNeck.addGuitarNeck("instrument");

			marksGauge = new Gauge("jauge_", ".gif");
			marksGauge.addGauge("marksGauge");

			noteKeyboard = new Keyboard(checkRoot, "C (do)", "C# Db", "D (ré)", "D# Eb", "E (mi)", "F (fa)", "F# Gb", "G (sol)", "G# Ab", "A (la)", "A# Bb", "B (si)");
			noteKeyboard.addKeyboard("noteKeyboard", 5);
			noteKeyboard = new Keyboard(checkName, "X", "Xm", "X7M", "X7", "Xm7", "Xm7(b5)", "X7M(9)", "X7(b9)", "X7(9)", "Xm7(9)", "X7(#11)", "Xdim", "X6", "Xm6", "X7(b13)", "X7(13)");
			noteKeyboard.addKeyboard("chordKeyboard", 6, 6);

			chordBase = new ChordBase();
			with (chordBase) {

				chordSet("Tous les accords");

				chordSet("Accords de base");
				// C
				add("X", 1, "x32010", true);
				add("Xm", 1, "x35543", true);
				add("X7", 1, "x32310", true);
				// D
				add("X", 2, "xx0232", true);
				add("Xm", 2, "xx0231", true);
				add("X7", 2, "xx0212", true);
				// E
				add("X", 0, "022100", true);
				add("Xm", 0, "022000", true);
				add("X7", 0, "020100", true);
				// F
				add("X", 0, "133211", true);
				add("Xm", 0, "133111", true);
				add("X7", 0, "131211", true);
				// G
				add("X", 0, "320003", true);
				add("X", 0, "320033", true);
				add("Xm", 0, "355333", true);
				add("X7", 0, "320001", true);
				// A
				add("X", 1, "x02220", true);
				add("X7", 1, "x02020", true);
				add("Xm", 1, "x02210", true);
				// B
				add("X", 1, "x24442", true);
				add("X7", 1, "x21202", true);
				add("Xm", 1, "x24432", true);

				chordSet("Grands barrés");

				add("X", 0, "022100");
				add("X7M", 0, "021100");
				add("X7", 0, "020100");
				add("Xm", 0, "022000");
				add("Xm7", 0, "020000");
				add("Xm7(b5)", 0, "0100xx");

				add("X", 1, "x02220");
				add("X7M", 1, "x02120");
				add("X7", 1, "x02020");
				add("Xm", 1, "x02210");
				add("Xm7", 1, "x02010");
				add("Xm7(b5)", 1, "x0101x");

				add("X", 2, "xx0232");
				add("X7M", 2, "xx0222");
				add("X7", 2, "xx0212");
				add("Xm", 2, "xx0231");
				add("Xm7", 2, "xx0211");
				add("Xm7(b5)", 2, "xx0111");

				chordSet("Petits barrés");

				add("X", 3, "xxx220");
				add("Xm", 3, "xxx210");

				add("X", 4, "xxx010");
				add("Xm", 4, "xxx120");

				add("X", 5, "xxx100");
				add("Xm", 5, "xxx000");

				chordSet("Enrichis");

				add("X7M", 0, "0x110x");
				add("X7", 0, "0x010x");
				add("Xm7", 0, "0x000x");

				add("X7M", 1, "x0x120");
				add("X7", 1, "x0x020");
				add("Xm7", 1, "x0x010");

				add("X7M", 2, "xx0x22");
				add("X7", 2, "xx0x12");
				add("Xm7", 2, "xx0x11");

				add("X6", 0, "1x021x");
				add("Xm6", 0, "1x011x");

				add("X6", 1, "x1x031");
				add("Xm6", 1, "x1x021");

				add("X7M(9)", 0, "1020xx");
				add("X7(b9)", 0, "2120xx");
				add("X7(9)", 0, "1010xx");
				add("Xm7(9)", 0, "2021xx");

				add("X7M(9)", 1, "x1021x");
				add("X7(b9)", 1, "x1010x");
				add("X7(9)", 1, "x1011x");
				add("Xm7(9)", 1, "x2022x");

				add("X7M(9)", 2, "xx1031");
				add("X7(b9)", 2, "xx1020");
				add("X7(9)", 2, "xx1021");
				add("Xm7(9)", 2, "xx2032");

				add("X7(#11)", 0, "1x120x");

				add("X7(#11)", 1, "x1x130");

				add("X7(b13)", 0, "0x011x");
				add("X7(13)", 0, "0x012x");

				add("X7(b13)", 1, "x0x021");
				add("X7(13)", 1, "x0x022");

				add("Xdim", 0, "1x010x");

				add("Xdim", 1, "x1x020");

				addChordSetSelector("chordSetSelector", chords.makeQuestion);
			}

			rootNode = textNode("?");
			nameNode = textNode("?");
			addTo("answerDisplay", rootNode, nameNode);
		}
	);

	function displayChord(layer, fret, chord, src) {
	/*	display chord notes on the guitar neck
		affiche les notes de l'accord sur le manche
	*/
		with (chord) {
			var base = fret - rootFret;
			for (var i = 0; i < fingerings.length; i++)
				if (fingerings[i] != null) guitarNeck.displayPosition(layer, i, 1*fingerings[i] + base, src);
		}
	}

	function offsetInBounds(rootFret, chord) {
	/*	returns how much the chord should be offset to fit into the neck (usually 0)
		rends le décalage nécessaire à faire entrer l'accord dans le manche (habituellement 0)
	*/
		var offset;
		if ((offset = rootFret + 1*chord.minFingeringOffset) < 0) return -offset;
		else if ((offset = rootFret + 1*chord.maxFingeringOffset) > 24) return 24 - offset;
		return 0;
	}

	var questionChord = null;
	var questionFret;
	var questionRoot;
	var questionName;

	var answerRoot;
	var answerName;

	this.makeQuestion = function() {
		guitarNeck.clearLayers();
		answerRoot = answerName = null;
		rootNode.data = nameNode.data = "?";
		var previousChord = questionChord;
		var previousRoot = questionRoot;
		for (var i = 0; i < 5; i++) {
			questionChord = chordBase.randomChord();
			questionFret = guitarNeck.randomFret();
			if (previousRoot != questionRoot) break;
			if (previousChord == null) break;
			if (previousChord.name != questionChord.name) break;
		}
		questionName = questionChord.name;
		if (questionChord.open) questionFret = questionChord.rootFret;
		else questionFret += offsetInBounds(questionFret, questionChord)
		questionRoot = guitarNeck.positionToNote(questionChord.rootString, questionFret);
		displayChord(1, questionFret, questionChord, "question_mark.gif");
	}

	var noteNames = new Array("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B");

	function checkRoot() {
		answerRoot = this.index;
		rootNode.data = noteNames[answerRoot];
		checkAnswer();
	}

	function checkName() {
		answerName = this.value;
		nameNode.data = answerName.substring(1);
		checkAnswer();
	}

	function checkAnswer() {
		if ((answerRoot == null) || (answerName == null)) return;
		if ((answerRoot == questionRoot) && (answerName == questionName)) {
			marksGauge.sum(1, 0);
			guitarNeck.clearLayer(0)
			displayChord(1, questionFret, questionChord, "green.gif");
			guitarNeck.displayCTone(questionChord.rootString);
			setTimeout("chords.makeQuestion()", 800);
			return;
		}
		marksGauge.sum(0, 1);
		var mistakeChord = chordBase.find(answerName, questionChord.rootString)
		if (mistakeChord == null) mistakeChord = questionChord;
		var mistake = answerRoot - questionRoot;
		if (mistake < -6) mistake += 12; else if (mistake >= 6) mistake -= 12;
		var mistakeFret = questionFret + mistake;
		var offset = offsetInBounds(mistakeFret, mistakeChord);
		if (offset < 0) mistakeFret -= 12; else if (offset > 0) mistakeFret += 12;
		guitarNeck.clearLayer(0)
		displayChord(0, mistakeFret, mistakeChord, "red.gif");
		answerRoot = answerName = null;
		rootNode.data = nameNode.data = "?";
	}

	addLoadEvent(this.makeQuestion);
}
