/*
* This file is part of the TraKERS\Front IDILL package.
*
* (c) IRI <http://www.iri.centrepompidou.fr/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/*
 * Projet : TraKERS
 * Module : Front IDILL
 * Fichier : search.js
 * 
 * Auteur : alexandre.bastien@iri.centrepompidou.fr
 * 
 * Fonctionnalités : Définit les fonctions de recherche par courbe de haut niveau (instantiation et manipulation de la classe de recherche par courbe mais pas les courbes en elles-mêmes ni le détecteur).
 */

/*
 * Lance une recherche par courbes.
 * Est appelé dans le fichier :
 * mosaic > fonction onMouseMove.
 */
Mosaic.prototype.startSearch = function()
{
    var _this = this;
    
    var top, left, width, height, margin_top, inMosaic;
    //Si on est dans le cas d'un filtrage de mosaïque.
    if(this.currentMode == "FILTER")
    {
        /*var mainPanel = $('#mainPanel');
        top = mainPanel.position().top;
        left = mainPanel.position().left;
        width = mainPanel.width();
        height = mainPanel.height();*/
        // margin_top = this.MPTop_margin;
        inMosaic = true;
    }
    //Sinon si c'est une recherche dans la vidéo.
    else if(this.currentMode == "SEARCH")
    {
        /*top = this.snTop;
        left = this.snLeft;
        width = this.snWidth;
        height = this.snHeight;*/
        // margin_top = '0px';
        inMosaic = false;
    }
    
    //On crée le canvas et on récupère le dictionnaire des courbes.
    // this.searchCanvas = new SearchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic, this);
    this.searchCanvas = new SearchCanvas(0, 0, $(window).width(), $(window).height(), 0, this.timeSearchFade, inMosaic, this);
    this.searchCanvas.create(this.dictionary);
}

/*
 * Lit le dictionnaire pour reconnaître les courbes de recherche.
 * Est appelé dans le fichier :
 * mosaic > fonction loadParameters.
*/
Mosaic.prototype.getDictionary = function()
{
    var path = (this.config.mouseInteractions ? this.config.curveDictionaryMI : this.config.curveDictionaryKI);
    var dico = [];
    
    var _this = this;
    
    $.getJSON(path, function(data)
    {
        //Chaque entrée comporte un objet de cette forme : (nom, tableau). Tableau est un array de strings, qui sont les codes décrivant la courbe. Chaque code est un alias de cette courbe.
        for(var i = 0 ; i < data.gestures.length ; i++)
        {
            _this.dictionary[i] = data.gestures[i];
        }
    });
}

/*
 * Charge le texte affichable en fonction de la langue.
 * Est appelé dans le fichier :
 * mosaic > fonction loadParameters.
*/
Mosaic.prototype.getLang = function(lang)
{
	//Si la langue choisie n'est pas disponible, on met l'anglais par défaut.
	if(this.config.langs.indexOf(this.config.lang) == -1)
	{
		this.config.lang = "en";
	}
	
    var path = 'lang/' + this.config.lang + '.json';
    
    var _this = this;
    
    $.getJSON(path, function(data)
    {
        _this.gesturesText = data.gesturesText;
		_this.notificationStrings = data.notificationStrings;
		_this.helpText = data.helpText;
		_this.creditsMetadata = data.credits_lang;
		_this.helpDetailsGesturesMetadata = data.gestures_help_metadata;
		_this.helpDetailsGestures = data.gestures_help;
    });
}

/*
 * Récupère le nom de code de chaque gesture ainsi que son nom de fichier de pictogramme pour l'aide.
*/
/*Mosaic.prototype.getGestures = function()
{
	//Chemion du fichier où sont stockées les noms de codes et noms d'images d'aide des gestures.
    var path = 'gestures.json';
    
    var _this = this;
    
    $.getJSON(path, function(data)
    {
        _this.gesturesImg = data.gesture_list.img;
    });
}*/

/*
 * Ecoute la position des pointeurs si les deux sont détectés afin de tracer des courbes de recherche.
*/
Mosaic.prototype.listenToPointers = function()
{
    if(this.searchCanvas)
    {
        
    }
}

/*
 * Quitte une recherche par courbes.
 * Est appelé dans les fichiers :
 * mosaic > fonction onMouseUp.
 * curvesDetector > fonction updateDists.
 */
Mosaic.prototype.leaveSearch = function()
{
    if(this.searchCanvas)
    {
        this.searchCanvas.leaveSearch();
		//Dans le cadre du mode d'interactions souris, on indique qu'on est en mouse down de facon à ne plus être en mouse move avant le prochain mouse up puis d'un mouse down.
		this.isMouseDown = false;
    }
    this.searchCanvas = null;
}

/*
 * Effectuer un filtrage de la mosaïque par rapport à un type de marqueurs.
 * Est appelé dans les fichiers :
 * mosaic > fonctions onMouseUp et manageControlEvents.
 * curvesDetector > fonction updateDists.
*/
Mosaic.prototype.searchFilter = function(type)
{
    var _this = this;
    
    //Si on est en mode filtrage.
    if(this.currentMode == "FILTER")
    {
        //On indique pour chaque snapshot la recherche de filtrage.
        for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
        {
            this.currentSearchGesture[i] = type;
        }
        
        this.filterSearchedType = type;
        
        //Si on a des annotations.
        if(this.annotations.length > 0)
        {
            //On indique qu'on est en train de filtrer.
            this.isMosaicFiltering = true;
            
            //Va servir à compter le nombre d'occurence des marqueurs dans chaque video.
            var gestureNumberByVideo = new Object();
            var maxAnnotationNumber = 0;
            
            //Pour chaque annotation.
            for(var i = 0 ; i < this.annotations.length ; i++)
            {
                //On récupère l'annotation en cours.
                var current = this.annotations[i];
                
                //Si l'annotation correspond à la gesture recherchée.
                if(current.annotationType.contents.title == type)
                {
                    //Si une video n'a pas été traitée, on met son nombre d'occurences à 0.
                    if(gestureNumberByVideo[current.source.url] == undefined || gestureNumberByVideo[current.source.url] == '')
                    {
                        gestureNumberByVideo[current.source.url] = 0;
                    }
                    
                    //On incrémente le nombre d'occurences de la video.
                    gestureNumberByVideo[current.source.url]++;
                }
            }
            
            //Pour chaque snapshot, s'il son nombre d'occurences n'a pas été encore calculé (cas où il n'y a pas de résultats dans ces videos là, on met leur nombre d'occurences à 0.
            for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
            {
                if(gestureNumberByVideo[this.urls[i]] == undefined || gestureNumberByVideo[this.urls[i]] == '')
                {
                    gestureNumberByVideo[this.urls[i]] = 0;
                }
            }
            
            //On récupère la vidéo qui score le nombre d'occurences de la gesture le plus haut.
            for(i in gestureNumberByVideo)
            {
                if(maxAnnotationNumber < gestureNumberByVideo[i])
                {
                    maxAnnotationNumber = gestureNumberByVideo[i];
                }
            }
            
            var snMargin = parseInt($('.snapshotDivs').css('margin-left'));
            
            //On affiche l'opacité résultante pour chaque vidéo.
            for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
            {
                //Opacité conventionelle.
                var opacity;
                if(maxAnnotationNumber > 0)
                {
                    opacity = gestureNumberByVideo[this.urls[i]] / maxAnnotationNumber;
                }
                else
                {
                    opacity = 0;
                }
                
                //Ce qui est à zéro le restera (par conséquent le snapshot associé sera invisible).
                if(opacity > 0)
                {
                    //On réhausse l'opacité de 50%.
                    opacity = this.scaleIntervals(0., 1., 0.5, 1., opacity);    
                }
                this.opacities[i] = opacity;
                
                var filterIndex = i;
                
                //On applique les opacités aux snapshots.
                $('#snapshotDiv-' + filterIndex).fadeTo(this.config['timeFilterFade'], opacity, function()
                {
                    //On indique lorsque c'est terminé que la mosaique a terminé de filtrer.
                    if(_this.isMosaicFiltering)
                    {
                        _this.isMosaicFiltering = false;
                    }
                });
                
                //Si l'opacité est nulle.
                if(opacity == 0)
                {
                    //Le snapshot filtré actuel.
                    var filteredSnapshot = $('#snapshotDiv-' + filterIndex);
                    
                    //S'il existe.
                    if(filteredSnapshot.length > 0)
                    {
                        //On rajoute un hider de façon à ce qu'on ne puisse pas le sélectionner.
                        var hider = '<div id="filterHider-' + filterIndex + '" class="filterHiders"></div>';
                        $('#mainPanel').append(hider);
                        
                        $('#filterHider-' + filterIndex).css(
                        {
                            width: +filteredSnapshot.width() + 4 * snMargin,
                            height: +filteredSnapshot.height() + 4 * snMargin,
                            top: filteredSnapshot.position().top - snMargin,
                            left: filteredSnapshot.position().left - snMargin
                        });
                    }
                }
            }
            
            //On indique que la mosaique a été filtrée.
            this.isMosaicFiltered = true;
        }
    }
}

/*
 * Passe une valeur de l'intervalle [A, B] à l'intervalle [C, D].
 * Est appelé dans les fichiers :
 * pointers > fonction pointersTimelineSelection.
 * search > fonction searchFilter.
*/
Mosaic.prototype.scaleIntervals = function(A, B, C, D, val)
{
    // return (D - C + A) * val + (C - A);
	if(A == B)
	{
		return (D - C) / 2;
	}
	else
	{
		return (D - C) * (val - A) / (B - A) + C;
	}
}

/*
 * Retourne l'index d'un snapshot en fonction de ses metadonnées.
*/
/*Mosaic.prototype.getIdxFromMetadata = function(metadata)
{
    var _this = this;
    
    for(idx in this.urls)
    {
        if(this.urls[idx] == metadata)
        {
            for(id in this.ids)
            {
                if(this.ids[id] == idx)
                {
                    return id;
                }
            }
        }
    }
    
    return -1;
}*/

/*
 * Enlève une recherche par filtre.
 * Est appelé : dans les fichiers :
 * pointers > fonctions checkIfPointerIsOnSearchNotification et removeSearchNotificationIfOnIt.
 * mosaic > fonction onMarkersReady.
*/
Mosaic.prototype.removeFilter = function()
{
    //Si on est en filtrage, on passe en mosaic et on retire la recherche.
    if(this.currentMode == "FILTER")
    {
        this.currentMode = "MOSAIC";
        
        var _this = this;
        
        this.isMosaicFiltered = false;
		this.isMosaicFiltering = true;
        this.filterSearchedType = '';
        
        for(var i = 0 ; i < this.config['imagesToShow'] ; i++)
        {
            this.currentSearchGesture[i] = '';
        }
        
        this.removeNotifications();
        $('.filterHiders').remove();
        $('.snapshotDivs').fadeTo(_this.config['timeFilterFade'], 1, function()
		{
			_this.isMosaicFiltering = false;
		});
    }
}

/*
 * Parcours le dictionnaire pour trouver la première gesture à avoir un code identique à celui en entrée.
 * Est appelé dans le fichier :
 * mosaic > fonction onMouseUp.
*/
Mosaic.prototype.gestureWithSameCode = function(code)
{
    //Pour tout le dictionnaire.
    for(var i = 0 ; i < this.dictionary.length ; i++)
    {
        //Pour touts les codes de chaque gesture du dictionnaire.
        for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
        {
            //Si le code en entrée est une partie début d'un des codes.
            if(this.dictionary[i].codes[j] === code || this.dictionary[i].codes[j].indexOf(code) == 0)
            {
                //On retourne le nom de la gesture.
                return this.dictionary[i].name;
            }
        }
    }
    
    return '';
}

/*
 * Extrait les données des crédits.
*/
Mosaic.prototype.getCredits = function()
{
	var _this = this;
	
	$.getJSON(this.config.creditsPath, function(data)
    {
        //On récupère les données des crédits et on les place dans un tableau avant de le retourner.
        for(var i = 0 ; i < data.creditsData.length ; i++)
        {
            _this.tabCredits[i] = data.creditsData[i];
        }
    });
}