/*
* 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 : searchCanvas.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).
 */

/*
 * Déclaration du canvas de recherche par courbes.
 * Est appelé dans le fichier :
 * search > fonction startSearch.
*/
function SearchCanvas(_canvasTop, _canvasLeft, _canvasWidth, _canvasHeight, _margin_top, _fadeTime, _inMosaic, _mosaic)
{
    //Coordonnées, dimensions et autres paramètres du canvas.
    this.canvasTop = _canvasTop;
    this.canvasLeft = _canvasLeft;
    this.canvasWidth = _canvasWidth;
    this.canvasHeight = _canvasHeight;
    this.fadeTime = _fadeTime;
    this.margin_top = _margin_top;
    
    this.mosaic = _mosaic;
    
    //Courbe du pointeur principal.
    this.mainPath;
    this.mainPathStroke;
    
    //Courbe du pointeur secondaire.
    this.secondPath;
    this.secondPathStroke;
    
    //Courbe indicatrice de la direction actuelle.
    this.direction;
    
    //Point précédent des pointeurs.
    this.mainLastPoint;
    this.secondLastPoint;
    
    //Coordonnées précédentes des pointeurs.
    this.mainPointerLastX;
    this.mainPointerLastY;
    this.secondPointerLastX;
    this.secondPointerLastY;
    
    this.inMosaic = _inMosaic;
    
    this.detector;
}

/*
 * Fonction d'initialisation du canvas de recherche par courbes.
 * Est appelé dans le fichier :
 * search > fonction startSearch.
*/
SearchCanvas.prototype.create = function(dictionary)
{
    var _this = this;
    
    //On crée le canvas.
    var canvas = '<canvas id="paperCanvas" width="' + this.canvasWidth + 'px" height="' + this.canvasHeight + 'px" class="canvas"></canvas>';
    //On l'ajoute à la page.
    $('body').append(canvas);
    
    $('.canvas').css(
    {
        top: this.canvasTop,
        left: this.canvasLeft
    });
    
    //S'il est dans la mosaique, on le réhausse en fonction de la taille de la marge verticale.
    if(this.inMosaic)
    {
        $('.canvas').css(
        {
            "margin-top": this.margin_top
        });
    }
    
    //On instancie le détecteur de courbes de recherche.
    this.detector = new CurvesDetector(6, 100, dictionary, this.mosaic);
    
    //On active le canvas.
    paper.setup('paperCanvas');
};

/*
 * Fonction appelée pour quitter le mode de recherche par courbes.
 * Est appelé dans le fichier :
 * search > fonction leaveSearch.
*/
SearchCanvas.prototype.leaveSearch = function()
{
    $('.canvas').fadeTo(this.fadeTime, 0, function()
    {
        $('.canvas').remove();
    });
    
    if(this.mosaic.isTablet)
    {
        this.mosaic.isTouchStart = false;
    }
};

/*
 * Fonction de déclaration des courbes.
 * Est appelé dans les fichiers :
 * mosaic > fonctions onMouseDown et onMouseMove.
 * client > fonction processMsg.
*/
SearchCanvas.prototype.onPointerIn = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
{
    // console.log('IN');
    
    if(this.mosaic.currentMode != 'MOSAIC' && this.mosaic.currentMode != 'FILTER')
    {
        mainPointerX -= 130;
        mainPointerY -= 60;
        
        if(secondPointerX && secondPointerY)
        {
            secondPointerX -= 130;
            secondPointerY -= 60;
        }
    }
    
    //On obtient les coordonnées du pointeur principal en px.
    mainPointerX = Math.floor(mainPointerX);
    mainPointerY = Math.floor(mainPointerY);
    
    //On forme le contour la courbe principale.
    this.mainPathStroke = new paper.Path();
    this.mainPathStroke.strokeColor = '#366F7A';
    this.mainPathStroke.strokeWidth = 18;
    this.mainPathStroke.strokeCap = 'round';
    this.mainPathStroke.strokeJoin = 'round';
    
    //On forme la courbe principale.
    this.mainPath = new paper.Path();
    this.mainPath.strokeColor = '#02FEFF';
    this.mainPath.strokeWidth = 10;
    this.mainPath.strokeCap = 'round';
    this.mainPath.strokeJoin = 'round';
    
    //Si on a un pointeur secondaire
    if(secondPointerX && secondPointerY)
    {
        //On obtient les coordonnées du pointeur secondaire en px.
        secondPointerX = Math.floor(secondPointerX);
        secondPointerY = Math.floor(secondPointerY);
        
        //On forme le contour de la courbe secondaire.
        this.secondPathStroke = new paper.Path();
        this.secondPathStroke.strokeColor = '#366F7A';
        this.secondPathStroke.strokeWidth = 18;
        this.secondPathStroke.strokeCap = 'round';
        this.secondPathStroke.strokeJoin = 'round';
        
        //On forme la courbe secondaire.
        this.secondPath = new paper.Path();
        this.secondPath.strokeColor = '#02FEFF';
        this.secondPath.strokeWidth = 10;
        this.secondPath.strokeCap = 'round';
        this.secondPath.strokeJoin = 'round';
    }
    
    //On raffraichit l'affichage.
    paper.view.draw();
};

/*
 * Fonction appelée lorsque les pointeurs bougent pour construire la courbe.
 * Est appelé dans les fichiers :
 * mosaic > fonction onMouseMove.
 * client > fonction processMsg.
*/
SearchCanvas.prototype.onPointerMove = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
{
    // console.log('MOVE');
    
    //Si on est dans une video, on réhausse
    if(this.mosaic.currentMode != 'MOSAIC' && this.mosaic.currentMode != 'FILTER' && this.mosaic.config.mouseInteractions)
    {
        // mainPointerX -= 130;
        // mainPointerY -= 60;
        
        if(secondPointerX && secondPointerY)
        {
            secondPointerX -= 130;
            secondPointerY -= 60;
        }
    }
    
    //On obtient les coordonnées du pointeur principal en px.
    mainPointerX = Math.floor(mainPointerX);
    mainPointerY = Math.floor(mainPointerY);
    
    //Si les coordonnées du pointeur principal n'ont pas été affectées, on les affecte.
    if(!this.mainPointerLastX || !this.mainPointerLastY)
    {
        this.mainPointerLastX = mainPointerX;
        this.mainPointerLastY = mainPointerY;
    }
    
    //On crée les points de la courbe principale.
    var mainPoint = new paper.Point(mainPointerX, mainPointerY);
    var mainPointStroke = new paper.Point(mainPointerX, mainPointerY);
    
    //On les ajoute à la courbe.
    this.mainPathStroke.add(mainPointStroke);
    this.mainPathStroke.smooth();
    
    //On place le premier point de la courbe, qu'on lisse.
    this.mainPath.add(mainPoint);
    this.mainPath.smooth();
    
    //Si on a un pointeur secondaire.
    if(secondPointerX && secondPointerY)
    {
        //On obtient les coordonnées du pointeur secondaire en px.
        secondPointerX = Math.floor(secondPointerX);
        secondPointerY = Math.floor(secondPointerY);
        
        //Si les coordonnées du pointeur principal n'ont pas été affectées, on les affecte.
        if(!this.secondPointerLastX || !this.secondPointerLastY)
        {
            this.secondPointerLastX = secondPointerX;
            this.secondPointerLastY = secondPointerY;
        }
        
        //On crée les points de la courbe secondaire.
        var secondPoint = new paper.Point(secondPointerX, secondPointerY);
        var secondPointStroke = new paper.Point(secondPointerX, secondPointerY);
        
        //On les ajoute à la courbe.
        this.secondPathStroke.add(secondPointStroke);
        this.secondPathStroke.smooth();
        
        //On place le premier point de la seconde courbe, qu'on lisse.
        this.secondPath.add(secondPoint);
        this.secondPath.smooth();
        
        //On met l'avant dernière position du pointeur secondaire à jour.
        if(this.secondPointerLastX != secondPointerX)
        {
            this.secondPointerLastX = secondPointerX;
        }
        if(this.secondPointerLastY != secondPointerY)
        {
            this.secondPointerLastY = secondPointerY;
        }
    }
    
    //On met l'avant dernière position du pointeur principal à jour.
    if(this.mainPointerLastX != mainPointerX)
    {
        this.mainPointerLastX = mainPointerX;
    }
    if(this.mainPointerLastY != mainPointerY)
    {
        this.mainPointerLastY = mainPointerY;
    }
    
    //On met à jour les points dans le détecteur de courbes.
    this.detector.updatePos(mainPointerX, mainPointerY, secondPointerX, secondPointerY);
    
    //On met à jour l'affichage.
    paper.view.draw();
};

/*
 * Fonction appelée lorsqu'on cesse de dessiner une courbe.
 * Est appelé dans les fichiers :
 * mosaic > fonction onMouseUp.
 * client > fonction processMsg.
*/
SearchCanvas.prototype.onPointerOut = function()
{
    // console.log('OUT');
    // console.trace();
    
    //On quitte la zone de recherche.
    this.isUserInSearchZone = false;
        
    //On regarde si ce qu'on a tracé correspond à une courbe en particulier.
    var gesture_match = this.mosaic.gestureWithSameCode(this.mosaic.actualCode);
    this.mosaic.actualCode = '';
    
    //Si oui.
    if(gesture_match.length > 0)
    {
        //Si on est en mode recherche dans une vidéo et que le player est prêt.
        if(this.mosaic.currentMode == "SEARCH" && this.mosaic.playerIsReady)
        {
            //On effectue une recherche dans cette vidéo.
            this.mosaic.player.widgets[0].searchByGesture(gesture_match);
            this.mosaic.isCurrentlyInASearchByGesture = this.mosaic.player.widgets[0].isCurrentlyInASearchByGesture;
            
            //On va au premier marqueur trouvé.
            if(this.mosaic.player && this.mosaic.player.widgets[0] && this.mosaic.timeToGoAt[this.mosaic.centerId] === 0 && this.mosaic.player.widgets[0].atLeastOneSearchMarker(this.mosaic.currentSearchGesture[this.mosaic.centerId]))
            {
                this.mosaic.player.widgets[0].goToFirstSearchedMarker(this.mosaic.currentSearchGesture[this.mosaic.centerId]);
            }
            
            //On affiche la notification de gesture de recherche.
            this.mosaic.removeNotifications();
            this.mosaic.currentSearchGesture[this.mosaic.centerId] = gesture_match;
            this.mosaic.searchGesture(gesture_match, 'valid');
            this.mosaic.curvesGesturesFound = false;
        }
        //Si on est en mode de filtrage de mosaique.
        else if(this.mosaic.currentMode == "FILTER")
        {
            if(this.mosaic.isMosaicFiltered)
            {
                //On notifie la recherche par filtrage.
                this.mosaic.removeNotifications();
                this.mosaic.filterSearchedType = gesture_match;
                this.mosaic.filterGesture(gesture_match, 'valid');
                //On filtre la mosaique.
                this.mosaic.searchFilter(gesture_match);
                this.mosaic.curvesGesturesFound = false;
            }
        }
    }
    //Si aucune gesture ne matche dans le dictionnaire.
    else if(!this.mosaic.mustTakeOutHands && this.mosaic.mouseInteractions)
    {
        //Si on était en mode filtrage de la mosaïque et qu'aucune gesture de filtrage n'avait été détectée avant ca, on revient en mode mosaïque.
        if(this.mosaic.currentMode == "FILTER" && this.mosaic.filterSearchedType == "")
        {
            this.mosaic.currentMode = "MOSAIC";
            this.mosaic.isMosaicFiltered = false;
        }
        //Sinon si on était en mode recherche dans une video et qu'aucune gesture n'avait été détectée avant ca, on revient en mode video.
        if(this.mosaic.currentMode == "SEARCH" && this.mosaic.currentSearchGesture[this.mosaic.centerId] == "")
        {
            this.mosaic.currentMode = "VIDEO";
        }
    }
    
    //On réinitialise la courbe principale.
    if(this.mainPathStroke)
    {
        this.mainPathStroke.remove();
    }
    if(this.mainPath)
    {
        this.mainPath.remove();
    }
    
    this.mainPointerLastX = 0;
    this.mainPointerLastY = 0;
    this.mainPointerX = 0;
    this.mainPointerY = 0;
    
    //On réinitialise le détecteur.
    this.detector.reinit();
    
    //Si on a un second pointeur, on réinitialise la courbe secondaire.
    if(this.secondPathStroke)
    {
        this.secondPathStroke.remove();
    }
    if(this.secondPath)
    {
        this.secondPath.remove();
    }
    
    //On met à jour l'affichage.
    paper.view.draw();
};