// Déclaration des variables

//Path
var img_path = "/img/";
var path = img_path+"manche/";
var base_url = "http://dicaccord.netne.net/index.php?seg0=site&seg1=dico";

// Liste des accords
var nb_accords;
var accords = new Array();
var accords_list;
var select;

// Configuration de la guitare
var accordage = new Array(4, 9, 2, 7, 11, 4);
var taille_manche = 22;

// Configuration de l'affichage des notes
var notes_chromatic = new Array(new Array("Do", "Do#", "Ré", "Ré#", "Mi", "Fa", "Fa#", "Sol", "Sol#", "La", "La#", "Si"),
                                new Array("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"));
var notes_text_list = new Array(new Array(" ", "Do", "Do# / Réb", "Ré", "Ré# / Mib", "Mi", "Fa", "Fa# / Solb", "Sol", "Sol# / Lab", "La", "La# / Sib", "Si"),
                                new Array(" ", "C", "C# / Db", "D", "D# / Eb", "E", "F", "F# / Gb", "G", "G# / Ab", "A", "A# / Bb", "B"));
var notes_nb = new Array(new Array(), new Array());

// Langage utilisé (0 = fr, 1 = us)
var lang = 0;

// Nombre de preview maximum
var nb_preview = 18;

// Variable nécessaire à l'affichage d'un accord par défaut
var accord_info = new Array();

// Variable d'information de l'accord courant
var selected_note;
var selected_type;
var selected_id;

window.onload = init();

// Initialisation de l'application
function init()
{
    for (var i = 0; i < 2; ++i)
        for (var j = 0; j < 12; ++j)
            notes_nb[i][notes_chromatic[i][j]] = j;
	selected_id = null;
	selected_note = null;
	selected_type = null;
    init_accord();
	init_url();
    preloader();
}

// Vérifie si l'url contient un accord précis
function init_url()
{
	var url = window.location.href;
	var get_var = url.slice(url.indexOf('?') + 1).split('&');
	var temp;
	accord_info[0] = null;

	for (var i = 0; i < get_var.length; ++i)
	{
		temp = get_var[i].split('=');
		if (temp[0] == 'accid')
			accord_info[0] = temp[1];
		if (temp[0] == 'acctype')
			accord_info[1] = temp[1];
		if (temp[0] == 'accnote')
			accord_info[2] = temp[1];
		if (temp[0] == 'acclang')
			accord_info[3] = temp[1];
	}
}

// Préchargement des images
function preloader ()
{
    var index = 0;
    document.img_tab = new Array();
    for (var i = 0; i < nb_accords; ++i)
    {
        document.img_tab[index] = new Image();
        document.img_tab[index++].src = path+'accord'+i+'.png';
    }
    for (var i = 0; i < nb_accords; ++i)
    {
        document.img_tab[index] = new Image();
        document.img_tab[index++].src = path+'accord'+i+'_head.png';
    }
    for (var i = 0; i < nb_accords; ++i)
    {
        document.img_tab[index] = new Image();
        document.img_tab[index++].src = path+'accord'+i+'_preview.png';
    }
    for (var i = 0; i < nb_accords; ++i)
    {
        document.img_tab[index] = new Image();
        document.img_tab[index++].src = path+'accord'+i+'_head_preview.png';
    }
}

// Changement du langage pour la notation
function chg_notation(language)
{
    var note_select = document.getElementById('note');
    if (language == 'fr')
        lang = 0;
    else
        lang = 1;
    // Vide le champ select
    while (note_select.options.length > 0)
        note_select.options[0] = null;
    
    // Rempli le select avec la bonne liste des notes
    var count = notes_text_list[lang].length;
    note_select.options[note_select.options.length] = new Option(" ", " ");
    for (var i = 1; i < count; ++i)
        note_select.options[note_select.options.length] = new Option(notes_text_list[lang][i], notes_chromatic[lang][i - 1]);
    note_select.options[0].selected = true;
}

// From www.developpez.com
function get_xhr()
{
    var xhr=null;
    if (window.XMLHttpRequest) { // Firefox et autres
        xhr = new XMLHttpRequest();
    }
    else if (window.ActiveXObject) { // Internet Explorer
        try {
            xhr = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            try {
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e1) {
                xhr = null;
            }
        }
    }
    else { // XMLHttpRequest non supporté par le navigateur
        alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
    }
    return xhr;
}

// Réception des données XML
function httpreponse(xhr)
{
    nb_accords = 0;
    var reponse = xhr.responseXML;
    if (xhr.readyState == 4 && xhr.status == 200)
    {
        var items = reponse.getElementsByTagName("item");
        // Création de la liste des accords
        for (var i = 0; i < items.length; ++i)
        {
            accords[nb_accords + 1] = new Array();
            accords[nb_accords + 1][0] = items[i].getElementsByTagName("id")[0].firstChild.data;
            accords[nb_accords + 1][1] = items[i].getElementsByTagName("type")[0].firstChild.data;
            accords[nb_accords + 1][2] = items[i].getElementsByTagName("scales")[0].firstChild.data;
            accords[nb_accords + 1][2] = accords[nb_accords + 1][2].split('-');
            accords[nb_accords + 1][3] = items[i].getElementsByTagName("schema")[0].firstChild.data;
            accords[nb_accords + 1][3] = accords[nb_accords + 1][3].split('');
            accords[nb_accords + 1][4] = items[i].getElementsByTagName("note")[0].firstChild.data;
            accords[nb_accords + 1][4] = accords[nb_accords + 1][4].split('');
            ++nb_accords;
        }
    }
}

// Récupération des données XML
function init_accord()
{
    var xhr = get_xhr();
    var url = "/xml/accords.xml";
    xhr.onreadystatechange = function() {httpreponse(xhr)};
    xhr.open("GET", url, true);
    xhr.send(null);
}

// RAZ de l'affichage du manche
function init_manche()
{
    for (var i = 1; i <= 5; ++i)
        document.getElementById('pos'+i).innerHTML = '';
    for (var i = 1; i <= 6; ++i)
    {
        document.getElementById('haut'+i).innerHTML = '';
        document.getElementById('bas'+i).innerHTML = '';
        document.getElementById('basnota'+i).innerHTML = '';
    }
    set_head(0);
}

// RAZ de l'affichage des previews
function init_preview()
{
    for (var i = 1; i <= nb_preview; ++i)
    {
        document.getElementById('prev'+i).src = path+'vide.png';
        document.getElementById('pos_prev'+i).innerHTML = '';
    }
}

// Changement d'accord
function chg_accord(sel)
{
	var note;
	var type = "";

	// Si la note n'est pas défini, lecture dans le select
	if (accord_info[0] == null)
		note = document.getElementById('note').options[document.getElementById('note').selectedIndex].value;
	else
		note = accord_info[2];

    if (sel != 0 || accord_info[0] == null)
        select = sel;
	else
		type = accord_info[1];

    init_preview();

	selected_note = note;

    // Defini le type d'accord
    switch (select)
    {
        case 1:
            type = document.getElementById('type').options[document.getElementById('type').selectedIndex].value;
            document.getElementById('alteres').options[0].selected = true;
            document.getElementById('enrichis').options[0].selected = true;
            break;
        case 2:
            type = document.getElementById('enrichis').options[document.getElementById('enrichis').selectedIndex].value;
            document.getElementById('alteres').options[0].selected = true;
            document.getElementById('type').options[0].selected = true;
            break;
        case 3:
            type = document.getElementById('alteres').options[document.getElementById('alteres').selectedIndex].value;
            document.getElementById('enrichis').options[0].selected = true;
            document.getElementById('type').options[0].selected = true;
            break;
        default:
            break;
    }

	selected_type = type;
	
    // Si une information sur la note ou le type est manquant, réinitialisation de l'affichage
    if (note != "" && type != "")
    {
        get_list(note, type);
        show_accord(0);
        show_preview();
    }
    else
    {
        // RAZ du manche
        init_manche();
        // Affichage des preview
        init_preview();
        // Affichage de l'accord
        show_img_accord(0, 1);
    }
}

// Défini une liste d'accord valide et trié pour une note et un type défini
function get_list(note, type)
{
    accords_list = new Array();
    var index = 0;
    var corde;
    var scales;
    var pos;
    var q;
    var h;
    var a;
    var place;

    // Recherche dans la liste des accords
    for (var i = 1; i < nb_accords + 1; ++i)
    {
        // Test si l'accord convient
        if (accords[i][1] == type)
        {
            // Recherche de la première corde de l'accord
            corde = get_first_corde(accords[i][2]);
            scales = new Array();
            // Recherche des différentes notes composant l'accord
            for (var j = 0; j < 6; ++j)
                scales[j] = get_note_scale(note, accords[i][2][j]);

            pos = -1;
            q = true;
            // Recherche des positions de l'accord
            while (q)
            {
                pos = get_position(corde, scales, pos + 1);
                if (pos == -1 || pos > taille_manche)
                    q = false;
                else
                {
                    // Vérification de la validité de l'accord
                    place = pos - accords[i][3][corde];
                    if (place >= -1)
                    {
                        // Accord valide
                        h = 0;
                        if (pos - accords[i][3][corde] < 0)
                            h = 1;
                        a = false;

                        // Test si c'est un accords spécifique à une note
                        if (accords[i][4] == "x")
                            a = true;
                        else if (accords[i][4] == notes_chromatic[1][notes_nb[lang][note]] && pos < 12)
                            a = true;
                        if (a == true)
                            accords_list[index++] = add_accord_list(i, corde, scales, pos, h);
                    }
                }
            }
        }
    }
    sort_accord_list();
}

// Tri (a bulle) d'une liste d'accord en fonction de sa position sur le manche, 
// puis privilégie les accords ouverts (Au début du manche)
function sort_accord_list()
{
    var temp = new Array();
    for (var i = 0; i < accords_list.length; ++i)
    {
        for (var j = 1; j < accords_list.length - i; ++j)
        {
            if (accords_list[j]['pos'] < accords_list[j - 1]['pos']
            || (accords_list[j]['pos'] == accords_list[j -1]['pos']
            && accords_list[j]['head'] > accords_list[j - 1]['head']))
            {
                temp = accords_list[j];
                accords_list[j] = accords_list[j - 1];
                accords_list[j - 1] = temp;
            }
        }
    }
}

// Ajoute un accord à une liste
function add_accord_list(id, corde, scales, pos, head)
{
    a = new Array();
    a['id'] = id;
    a['corde'] = corde;
    a['scales'] = scales;
    a['pos'] = pos;
    a['head'] = head;
    return a;
}

// Affichage de l'accord et de ces informations
function show_accord(index)
{
    var id = accords_list[index]['id'];
    var pos = accords_list[index]['pos'];
    var corde = accords_list[index]['corde'];
    var d = 0;
	var note;
	
	selected_id = id;
	
	// Si la note n'est pas défini, lecture dans le select
	if (accord_info[0] == null)
		note = document.getElementById('note').options[document.getElementById('note').selectedIndex].value;
	else
		note = accord_info[2];

    init_manche();
    var p = parseInt(accords[id][3][corde]);
    // Test si l'accord se trouve au début du manche pour l'affichage du sillet
    if (accords_list[index]['head'] == 1 || pos <= accords[id][3][corde])
        set_head(1);
    if (pos - p < 0)
    {
        pos = 0;
        d = -1;
    }
    
    // Affichage de la position de l'accord
    if (pos > 1)
        document.getElementById('pos'+(p + d)).innerHTML = pos;
    
    // Affichage des notes et intervalles
    for (var i = 0; i < 6; ++i)
    {
        // Affichage des informations pour les cordes à vide
        if (accords[id][3][i] == 'x')
            document.getElementById('haut'+(i + 1)).innerHTML = 'X';
        else if (accords[id][3][i] == '1' && accords_list[index]['head'] == 1)
        {
            document.getElementById('haut'+(i + 1)).innerHTML = '0';
        }
        
        // Affichage des notes
        document.getElementById('bas'+(i + 1)).innerHTML = get_note_scale(note, accords[id][2][i]);
        // Affichage des intervalles
        if (accords[id][2][i] != 'x')
            document.getElementById('basnota'+(i + 1)).innerHTML = accords[id][2][i];
    }
    show_img_accord(id, pos);
}

// Affichage des preview
function show_preview()
{
    var count = accords_list.length;
    var prev_index = 1;
    for (var i = 0; i < count; ++i)
    {
        if (accords_list[i]['head'] == 1)
            document.getElementById('prev'+prev_index).src = path+'accord'+accords_list[i]['id']+'_head_preview.png';
        else
            document.getElementById('prev'+prev_index).src = path+'accord'+accords_list[i]['id']+'_preview.png';
        document.getElementById('pos_prev'+prev_index).innerHTML = accords_list[i]['pos'];
        prev_index++;
    }
}

// Affichage du sillet
function set_head(show)
{
    if (show == 0)
        document.getElementById('sillet').src = '';
    else
        document.getElementById('sillet').src = path+'sillet.png'
}

// Affichage des images des accords
function show_img_accord(id, pos)
{
    var ext = '.png';
    if (pos == 0)
        ext = '_head'+ext;
    document.getElementById('accord').src = path+'accord'+id+ext;
}

// Renvoi l'indice de la première corde de l'indice
function get_first_corde(accord)
{
    var i = 0;
    while (accord[i] == 'x')
        ++i;
    return i;
}

// Renvoi la note par rapport à une note de base et un intervale
function get_note_scale(note, scale)
{
    switch (scale)
    {
        case 'F':
            return note;
        case '2m':
        case '9d':
            return get_text_note((notes_nb[lang][note] + 1)%12);
        case '2M':
        case '9':
            return get_text_note((notes_nb[lang][note] + 2)%12);
        case '3m':
        case '9a':
            return get_text_note((notes_nb[lang][note] + 3)%12);
        case '3M':
            return get_text_note((notes_nb[lang][note] + 4)%12);
        case '4j':
        case '11':
            return get_text_note((notes_nb[lang][note] + 5)%12);
        case '4a':
        case '5d':
            return get_text_note((notes_nb[lang][note] + 6)%12);
        case '5j':
            return get_text_note((notes_nb[lang][note] + 7)%12);
        case '5a':
        case '6m':
        case '13m':
            return get_text_note((notes_nb[lang][note] + 8)%12);
        case '6M':
        case '13M':
        case '7d':
            return get_text_note((notes_nb[lang][note] + 9)%12);
        case '7m':
            return get_text_note((notes_nb[lang][note] + 10)%12);
        case '7M':
            return get_text_note((notes_nb[lang][note] + 11)%12);
        case 'x':
            return '';
    }
}

// Renvoie la note sous forme texte
function get_text_note(note)
{
    return notes_chromatic[lang][note%12];
}

// Renvoi la position de l'accord sur le manche
function get_position(corde, notes, index)
{
    // Recherche de la première note de l'accord
    var j = 0;
    var debut = accordage[corde] + index;
    while (notes[corde] != get_text_note(debut + j) && j < 25)
        ++j;
    if (j >= 25)
        return -1;
    return j + index;
}

// Copie le lien d'un accord dans le presse papier
function copie_accord()
{
	if (selected_id != null)
		document.getElementById('text_clipboard').value = base_url+'&acclang='+lang+'&acctype='+selected_type+'&accid='+selected_id+'&accnote='+notes_chromatic[1][notes_nb[lang][selected_note]];
	document.getElementById('div_clipboard').style.display = 'block';
	document.getElementById('text_clipboard').select();
}

// Fermer la fenêtre pour le presse papier
function close_accord()
{
	document.getElementById('div_clipboard').style.display = 'none';
}

// Affichage d'un accord initiale si il est défini dans l'url
function show_init_accord()
{
	if (accord_info[0] != null)
	{
		var nb_note = notes_nb[1][accord_info[2]];
		var k = 0;
		
		// Test du langage
		if (accord_info[3] == 1)
			lang = 1;
		else
		{
			// Convertir la note de l'anglais vers le français
			accord_info[2] = notes_chromatic[0][nb_note];
		}
		// Affichage de l'accord de base et des previews
		chg_accord(0);
		// Recherche de l'index de l'accord avec l'id
		for (var i = 0; i < accords_list.length; ++i)
			if (accords_list[i]['id'] == accord_info[0])
			{
				k = i;
				i = accords_list.length;
			}
		// Affichage de l'accord voulu
		show_accord(k);
		
		// Affichage des informations dans les selects
		if (lang == 1)
		{
			chg_notation('us');
			document.getElementById('lang_us').checked = true;
		}
		document.getElementById('note').options[nb_note + 1].selected = true;
		var q = true;
		var count = document.getElementById('type').options.length;

		for (var i = 0; i < count; ++i)
			if (document.getElementById('type').options[i].value == accord_info[1])
			{
				q = false;
				document.getElementById('type').options[i].selected = true;
			}
	}
}

