/*
* This file is part of the TraKERS\Middleware 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 : MIDDLEWARE
 * Sous-Module : Debug
 * Classe : DebugWindow
 * 
 * Auteur : alexandre.bastien@iri.centrepompidou.fr
 * 
 * Fonctionnalités : Reçoit des notifications des sous-modules Tracking, Communication et Exception.
 * Intéragit avec la fenêtre XAML de debug de façon à afficher un rendu visuel.
 */

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Drawing;
using Microsoft.Kinect;
using System.Resources;
using System.Reflection;
using System.Timers;
using System.Configuration;

namespace Trakers.Debug
{
    public partial class DebugWindow : Window
    {
        //Gestionnaire de ressources.
        private ResourceManager rm;

        //Paramètres du serveur TUIO.
        private string connexionHost;
        private int connexionPort;
        //Temps de rafraichissement pour le timer (Détection de gesture dans le serveur TUIO).
        private int timerElapsing;
        //Distances min/max délimitant le champ de recherche.
        private float minDistHands;
        private float maxDistHands;
        private float minDist;
        private float maxDist;
        private float zeroPoint;
        //Paramètres de la mosaïque.
        private int imagesToShow;
        //Paramètres de la recherche par courbes.
        private int takenPoints;
        private int directionChangeTresholdXY;
        private float directionChangeTresholdZ;
        //Images
        private String imgLocation;

        //Timer.
        private System.Timers.Timer _timer;
        //Membre permettant d'atteindre la classe KinectMain du sous-module Tracking.
        //private KinectMain kinectMain;
        //Tableau contenant une image en couleurs.
        private byte[] colorPixelData;
        //Indique si la kinect est allumée/éteinte.
        private bool on;
        //Indique si la fenêtre de debug est actuellement en cours de fermeture.
        private bool closing;
        //Indique si l'image doit être raffraichie.
        private Boolean refreshImage;
        //Fenêtre de paramètres
        private DebugParameters param;

        /*
        * Constructeur : Affiche la fenêtre de debug en lui passant en paramètre une instanciation de la
        * classe KinectMain.
        * Au départ, la kinect est éteinte.
        */
        public DebugWindow()//KinectMain main)
        {
            InitializeComponent();

            imgLocation = "Imgs";

            //On fait appel au gestionnaire de ressources.
            rm = new ResourceManager("Trakers.Debug.Properties.Resources", Assembly.GetExecutingAssembly());
            //On tente de charger les paramètres du fichier params.ini.
            //Si on n'y arrive pas, on affiche une erreur et on charge les paramètres par défaut.
            if (!loadParameters())
            {
                ExceptionLbl.Content = rm.GetString("loadParametersFail");
                //Distances de détection des mains par défaut pour la recherche (ici de 1m à 2m de la Kinect).
                minDistHands = 1.0f;
                maxDistHands = 1.5f;
                minDist = 1.0f;
                maxDist = 4.0f;
                zeroPoint = 1.7f;
                connexionHost = "127.0.0.1";
                connexionPort = 80;
                timerElapsing = 1000;
                imagesToShow = 25;
                takenPoints = 10;
                directionChangeTresholdXY = 10;
                directionChangeTresholdZ = 0.01f;
            }

            //On charge la fenêtre de paramètres.
            param = new DebugParameters(this);

            //kinectMain = main;
            on = true;
            closing = false;
            refreshImage = true;
            try
            {
                //On instancie le timer à N ms.
                _timer = new System.Timers.Timer(timerElapsing);
                //Dès que le timer est expiré, on appelle _timer_Elapsed.
                _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
            }
            catch (Exception){}
        }

        /*
         * Méthode d'effacement du label d'exceptions.
         */
        public void NoException()
        {
            ExceptionLbl.Content = "";
        }

        /*
         * Méthode d'affichage des exceptions dans le label d'exceptions.
         */
        public void ShowException(String reference)
        {
            ExceptionLbl.Content = rm.GetString(reference);
        }

        /*
         * Méthode de fermeture de l'interface.
         */
        public void ShutDownInterface()
        {
            DebugImage.Source = null;
            ExceptionLbl.Content = "";
        }

        /*
         * Méthode appelée à l'expiration du timer pour les gestures et modes.
         */
        public void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            //On débloque le raffraichissement de l'image.
            refreshImage = true;
            //On arrête le timer.
            _timer.Stop();
        }

        /*
        * Getter pour le membre indiquant la fermeture de la fenêtre de debug.
        */
        public bool isClosing()
        {
            return closing;
        }

        /*
        * Est appelée à la fermeture de la fenêtre.
        */
        public void Window_Closed(object sender, EventArgs e)
        {
            closing = true;
        }

        /*
        * Bouton ON/OFF.
        */
        private void Switch_Click(object sender, RoutedEventArgs e)
        {
            //S'il valait faux, il vaut vrai maintenant et inversement.
            on = !on;
            //Si la kinect est allumée.
            if (on)
            {
                //Il affiche OFF (pour éteindre la kinect).
                Switch.Content = "OFF";
                //On vide le label des exceptions.
                ExceptionLbl.Content = "";
            }
            else
            {
                //Il affiche ON (pour allumer la kinect).
                Switch.Content = "ON";
                //On remet à zéro tous les éléments du retour visuel.
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                DistanceLbl.Content = "Distance :";
                LeftHand.Background = System.Windows.Media.Brushes.DarkGray;
                LeftHand.Content = "";
                RightHand.Background = System.Windows.Media.Brushes.DarkGray;
                RightHand.Content = "";
                DebugCanvas.Children.RemoveRange(1, DebugCanvas.Children.Count - 1);
            }
        }

        /*
        *  Récupère le flux video et met à jour le rendu visuel de debug.
        */
        public void RefreshVideo(AllFramesReadyEventArgs e)
        {
            if (refreshImage)
            {
                bool receivedData = false;
                ColorImageFrame colorImageFrameData;
                using (colorImageFrameData = e.OpenColorImageFrame())
                {
                    //Si on ne reçoit pas de trames de la kinect.
                    if (colorImageFrameData == null)
                    {
                        //L'image est supprimée.
                        DebugImage.Source = null;
                    }
                    //Si le tableau stockant l'image en cours est nul.
                    if (colorPixelData == null)
                        //On alloue un nouveau tableau.
                        colorPixelData = new byte[colorImageFrameData.PixelDataLength];
                    else
                    {
                        try
                        {
                            //Sinon on met à jour le tableau en copiant le contenu de la trame dans le tableau.
                            colorImageFrameData.CopyPixelDataTo(colorPixelData);
                            receivedData = true;
                        }
                        catch (Exception) { }
                    }
                }
                //Si on a des données dans le tableau et que la kinect est allumée.
                if (receivedData && on)
                {
                    //On met à jour l'image de la caméra.
                    DebugImage.Source = BitmapSource.Create(colorImageFrameData.Width, colorImageFrameData.Height, 96, 96, PixelFormats.Bgr32, null, colorPixelData, colorImageFrameData.Width * colorImageFrameData.BytesPerPixel);
                    DebugImage.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
                    DebugImage.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                    DebugImage.Stretch = Stretch.Fill;
                    //On annule l'image associée aux gestures.
                    Gestures.Source = null;
                }
            }
        }

        /*
        * Affiche la distance de l'utilisateur dans le rendu visuel.
        * Sous forme de nombre en m et de rectangles changeant de couleur en fonction de la distance.
        */
        public void showDistance(float proximity)
        {
            DistanceLbl.Content = "Proximity : " + proximity + "%";

            if (proximity == 0)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
                R6.Fill = System.Windows.Media.Brushes.DarkGray;
                R7.Fill = System.Windows.Media.Brushes.DarkGray;
                R8.Fill = System.Windows.Media.Brushes.DarkGray;
                R9.Fill = System.Windows.Media.Brushes.DarkGray;
                R10.Fill = System.Windows.Media.Brushes.DarkGray;
            }
            else if (proximity > 0 && proximity < 10)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
                R6.Fill = System.Windows.Media.Brushes.DarkGray;
                R7.Fill = System.Windows.Media.Brushes.DarkGray;
                R8.Fill = System.Windows.Media.Brushes.DarkGray;
                R9.Fill = System.Windows.Media.Brushes.DarkGray;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 10 && proximity < 20)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
                R6.Fill = System.Windows.Media.Brushes.DarkGray;
                R7.Fill = System.Windows.Media.Brushes.DarkGray;
                R8.Fill = System.Windows.Media.Brushes.DarkGray;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 20 && proximity < 30)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
                R6.Fill = System.Windows.Media.Brushes.DarkGray;
                R7.Fill = System.Windows.Media.Brushes.DarkGray;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 30 && proximity < 40)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
                R6.Fill = System.Windows.Media.Brushes.DarkGray;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 40 && proximity < 50)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 50 && proximity < 60)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
                R5.Fill = System.Windows.Media.Brushes.Orange;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 60 && proximity < 70)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
                R4.Fill = System.Windows.Media.Brushes.Yellow;
                R5.Fill = System.Windows.Media.Brushes.Orange;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 70 && proximity < 80)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
                R3.Fill = System.Windows.Media.Brushes.Yellow;
                R4.Fill = System.Windows.Media.Brushes.Yellow;
                R5.Fill = System.Windows.Media.Brushes.Orange;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 80 && proximity < 90)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
                R2.Fill = System.Windows.Media.Brushes.Yellow;
                R3.Fill = System.Windows.Media.Brushes.Yellow;
                R4.Fill = System.Windows.Media.Brushes.Yellow;
                R5.Fill = System.Windows.Media.Brushes.Orange;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity > 90 && proximity < 100)
            {
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
                R1.Fill = System.Windows.Media.Brushes.Yellow;
                R2.Fill = System.Windows.Media.Brushes.Yellow;
                R3.Fill = System.Windows.Media.Brushes.Yellow;
                R4.Fill = System.Windows.Media.Brushes.Yellow;
                R5.Fill = System.Windows.Media.Brushes.Orange;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
            else if (proximity == 100)
            {
                R0.Fill = System.Windows.Media.Brushes.Green;
                R1.Fill = System.Windows.Media.Brushes.Yellow;
                R2.Fill = System.Windows.Media.Brushes.Yellow;
                R3.Fill = System.Windows.Media.Brushes.Yellow;
                R4.Fill = System.Windows.Media.Brushes.Yellow;
                R5.Fill = System.Windows.Media.Brushes.Orange;
                R6.Fill = System.Windows.Media.Brushes.Orange;
                R7.Fill = System.Windows.Media.Brushes.Orange;
                R8.Fill = System.Windows.Media.Brushes.Red;
                R9.Fill = System.Windows.Media.Brushes.Red;
                R10.Fill = System.Windows.Media.Brushes.Red;
            }
        }

        /*
        * Affiche la détection de la main droite via un label.
        */
        public void showRightHandRect(bool show)
        {
            if (show)
                RightHand.Background = System.Windows.Media.Brushes.Blue;
            else
                RightHand.Background = System.Windows.Media.Brushes.DarkGray;
        }

        /*
        * Affiche la détection de la main gauche via un label.
        */
        public void showLeftHandRect(bool show)
        {
            if (show)
                LeftHand.Background = System.Windows.Media.Brushes.Blue;
            else
                LeftHand.Background = System.Windows.Media.Brushes.DarkGray;
        }

        /*
        * Dessine les noeuds du squelette dans le rendu visuel.
        */
        public void drawJoints(JointCollection joints, Skeleton first)
        {
            if (refreshImage)
            {
                //On enlève tout élément du Canvas à part l'image, de manière à mettre à jour la position du squelette. 
                DebugCanvas.Children.RemoveRange(1, DebugCanvas.Children.Count - 1);

                //Pour chaque noeud.
                foreach (Joint joint in first.Joints)
                {
                    //On crée une ellipse de taille 20 et de largeur 20.
                    Ellipse node = new Ellipse();
                    node.Height = 20;
                    node.Width = 20;

                    //S'il s'agit d'un noeud de tête, on le colorie en rouge, sinon en bleu.
                    if (joint.JointType == JointType.Head)
                        node.Fill = System.Windows.Media.Brushes.Red;
                    else if (joint.JointType == JointType.ShoulderCenter)
                        node.Fill = System.Windows.Media.Brushes.Green;
                    else if (joint.JointType == JointType.HipCenter)
                        node.Fill = System.Windows.Media.Brushes.Green;
                    else if (joint.JointType == JointType.HandRight)
                        node.Fill = System.Windows.Media.Brushes.Red;
                    else
                        node.Fill = System.Windows.Media.Brushes.Blue;

                    //On met à la bonne échelle les coordonnées des positions des noeuds.
                    Joint scaledJoint = Coding4Fun.Kinect.Wpf.SkeletalExtensions.ScaleTo(joint, 600, 400, 0.75f, 0.75f);

                    //On positionne le noeud dans le Canvas, et on l'ajoute.
                    Canvas.SetLeft(node, scaledJoint.Position.X);
                    Canvas.SetTop(node, scaledJoint.Position.Y);
                    DebugCanvas.Children.Add(node);
                }
            }
        }

        /*
        * Dessine un os, en ayant en paramètres deux noeuds.
        */
        public void drawBone(Joint j1, Joint j2)
        {
            //On crée une nouvelle ligne verte d'épaisseur 8 entre les deux noeuds et on l'ajoute au Canvas.
            Line line = new Line();
            line.Stroke = System.Windows.Media.Brushes.Green;
            line.X1 = j1.Position.X;
            line.X2 = j2.Position.X;
            line.Y1 = j1.Position.Y;
            line.Y2 = j2.Position.Y;
            line.StrokeThickness = 8;
            DebugCanvas.Children.Add(line);
        }

        /*
        * Dessine le squelette (ensemble des os), en ayant en paramètres tous les noeuds.
        */
        public void showSkeleton(Joint hipCenter, Joint spine, Joint shoulderCenter, Joint head, Joint shoulderLeft, Joint elbowLeft, Joint wristLeft, Joint handLeft, Joint shoulderRight, Joint elbowRight, Joint wristRight, Joint handRight, Joint hipLeft, Joint kneeLeft, Joint ankleLeft, Joint footLeft, Joint hipRight, Joint kneeRight, Joint ankleRight, Joint footRight)
        {
            if (refreshImage)
            {
                //On met les noeuds deux par deux en fonction de leur position dans le squelette.
                drawBone(head, shoulderCenter);
                drawBone(shoulderCenter, shoulderLeft);
                drawBone(shoulderLeft, elbowLeft);
                drawBone(elbowLeft, wristLeft);
                drawBone(wristLeft, handLeft);
                drawBone(shoulderCenter, shoulderRight);
                drawBone(shoulderRight, elbowRight);
                drawBone(elbowRight, wristRight);
                drawBone(wristRight, handRight);
                drawBone(shoulderCenter, spine);
                drawBone(spine, hipCenter);
                drawBone(hipCenter, hipLeft);
                drawBone(hipLeft, kneeLeft);
                drawBone(kneeLeft, ankleLeft);
                drawBone(ankleLeft, footLeft);
                drawBone(hipCenter, hipRight);
                drawBone(hipRight, kneeRight);
                drawBone(kneeRight, ankleRight);
                drawBone(ankleRight, footRight);
            }
        }

        /*
        * Cache le squelette et le reste de l'interface à part l'image.
        */
        public void hideSkeleton()
        {
            //On vide le canvas mais en gardant l'image.
            if(DebugCanvas.Children.Count > 1)
                DebugCanvas.Children.RemoveRange(1, DebugCanvas.Children.Count - 1);
            //On colore en gris tous les indicateurs.
            R0.Fill = System.Windows.Media.Brushes.DarkGray;
            R1.Fill = System.Windows.Media.Brushes.DarkGray;
            R2.Fill = System.Windows.Media.Brushes.DarkGray;
            R3.Fill = System.Windows.Media.Brushes.DarkGray;
            R4.Fill = System.Windows.Media.Brushes.DarkGray;
            R5.Fill = System.Windows.Media.Brushes.DarkGray;
            R6.Fill = System.Windows.Media.Brushes.DarkGray;
            R7.Fill = System.Windows.Media.Brushes.DarkGray;
            R8.Fill = System.Windows.Media.Brushes.DarkGray;
            R9.Fill = System.Windows.Media.Brushes.DarkGray;
            R10.Fill = System.Windows.Media.Brushes.DarkGray;
        }

        /*
        * Affiche la position de la main gauche dans le rendu visuel.
        */
        public void showLeftHandCoord(String coord)
        {
            LeftHand.Content = coord;
        }

        /*
        * Affiche la position de la main gauche dans le rendu visuel.
        */
        public void showRightHandCoord(String coord)
        {
            RightHand.Content = coord;
        }

        /*
         * Méthode associée à l'événement : Ouvrir la fenêtre de paramétrage via le menu.
         */
        private void Parameters_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                param.ShowDialog();
            }
            catch (Exception)
            {
                ExceptionLbl.Content = rm.GetString("loadParamFail");
            }
        }

        /*
         * Méthode associée à l'événement : Quitter via le menu.
         */
        public void Quit_Click(object sender, RoutedEventArgs e)
        {
            closing = true;
            //On éteint la Kinect (pour éviter qu'elle reste allumée même lorsque le programme est éteint).
 
            Application.Current.Shutdown();
        }

        /*
         * Permet d'initialiser la Kinect dès que la fenêtre est lancée.
         */
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //kinectMain.KinectInitialization();
        }

        /*
         * Permet d'obtenir l'image associée à l'emplacement des images si celle-ci existe.
         */
        public Bitmap getImage(String location)
        {
            try
            {
                return new Bitmap(location);
            }
            catch (Exception)
            {
                return (Bitmap)rm.GetObject("_404");
            }
        }

        /*
         * Méthode d'affichage des gestures.
         */
        public void showGesture(String gesture)
        {
            if (refreshImage)
            {
                refreshImage = false;
                _timer.Start();
                Bitmap bitmap = null;
                //S'il s'agit de telle ou telle gesture, on prend l'image correspondante dans les ressources,
                //on la convertit et on l'affiche.
                switch (gesture)
                {
                    case "SWIPE-LEFT": bitmap = getImage(imgLocation + "\\swipe_left.png");
                        break;
                    case "SWIPE-RIGHT": bitmap = getImage(imgLocation + "\\swipe_right.png");
                        break;
                    case "PUSH-RIGHT": bitmap = getImage(imgLocation + "\\push_right.png");
                        break;
                    case "PUSH-LEFT": bitmap = getImage(imgLocation + "\\push_left.png");
                        break;
                    case "PUSH-BOTH": bitmap = getImage(imgLocation + "\\push_both.png");
                        break;
                    case "PULL-RIGHT": bitmap = getImage(imgLocation + "\\pull_right.png");
                        break;
                    case "PULL-LEFT": bitmap = getImage(imgLocation + "\\pull_left.png");
                        break;
                    case "PULL-BOTH": bitmap = getImage(imgLocation + "\\pull_both.png");
                        break;
                    case "WAVE": bitmap = getImage(imgLocation + "\\wave.png");
                        break;
                    case "BEND": bitmap = getImage(imgLocation + "\\bend.png");
                        break;
                    case "CROSS": bitmap = getImage(imgLocation + "\\cross.png");
                        break;
                    case "KNEE-UP": bitmap = getImage(imgLocation + "\\knee_up.png");
                        break;
                }
                Gestures.Source = CreateBitmapSourceFromBitmap(bitmap);
            }

            DebugImage.Source = null;
            hideSkeleton();
        }

        /*
         * Méthode d'indication de raffraichissement de l'image ("on la raffraichit ou pas ?").
         */
        public void setRefreshImage(bool refresh)
        {
            refreshImage = refresh;
        }

        /*
         * Méthode de conversion de Bitmap (des ressources) en BitmapSource (du debug).
         */
        public static BitmapSource CreateBitmapSourceFromBitmap(Bitmap bitmap)
        {
            if (bitmap == null)
                return null;

            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                bitmap.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
        }

        /*
        *  Méthode de chargement des paramètres (position du champ de recherche...).
        */
        public bool loadParameters()
        {
            try
            {
                minDistHands = Properties.Settings.Default.searchMinDistance;
                maxDistHands = Properties.Settings.Default.searchMaxDistance;
                minDist = Properties.Settings.Default.minDistance;
                maxDist = Properties.Settings.Default.maxDistance;
                zeroPoint = Properties.Settings.Default.zeroPoint;
                connexionHost = Properties.Settings.Default.connexionHost;
                connexionPort = Properties.Settings.Default.connexionPort;
                timerElapsing = Properties.Settings.Default.timerElapsing;
                imagesToShow = Properties.Settings.Default.imagesToShow;
                takenPoints = Properties.Settings.Default.takenPoints;
                directionChangeTresholdXY = Properties.Settings.Default.directionChangeTresholdXY;
                directionChangeTresholdZ = Properties.Settings.Default.directionChangeTresholdZ;
            }
            catch (Exception)
            {
                return false;
            }

            if (maxDistHands <= 0f || minDistHands <= 0f || maxDistHands > maxDist || minDistHands > maxDist ||
                minDistHands >= maxDistHands || zeroPoint < maxDistHands || minDistHands > minDist ||
                zeroPoint >= maxDist || connexionPort < 0 || timerElapsing < 0 || imagesToShow < 1 ||
                takenPoints <= 0 || directionChangeTresholdXY < 0 || directionChangeTresholdZ < 0)
            {
                ExceptionLbl.Content = rm.GetString("loadParametersIncorrect");
                return false;
            }
            return true;
        }

        /*
         * Met à jour les nouveaux paramètres dans la configuration.
         */
        public void updateParameters()
        {
            //userPositionDetector.setParams(minDist, maxDist, minDistHands, maxDistHands, zeroPoint);
            //segmenter.setParams(takenPoints, directionChangeTresholdXY, directionChangeTresholdZ);

            //On récupère la config.
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            //On met à jour.
            Properties.Settings.Default.Context.Remove("searchMinDistance");
            Properties.Settings.Default.Context.Add("searchMinDistance", minDistHands.ToString());
            Properties.Settings.Default.Context.Remove("searchMaxDistance");
            Properties.Settings.Default.Context.Add("searchMaxDistance", maxDistHands.ToString());
            Properties.Settings.Default.Context.Remove("minDistance");
            Properties.Settings.Default.Context.Add("minDistance", minDist.ToString());
            Properties.Settings.Default.Context.Remove("maxDistance");
            Properties.Settings.Default.Context.Add("maxDistance", maxDist.ToString());
            Properties.Settings.Default.Context.Remove("zeroPoint");
            Properties.Settings.Default.Context.Add("zeroPoint", zeroPoint.ToString());
            Properties.Settings.Default.Context.Remove("connexionHost");
            Properties.Settings.Default.Context.Add("connexionHost", connexionHost);
            Properties.Settings.Default.Context.Remove("connexionPort");
            Properties.Settings.Default.Context.Add("connexionPort", connexionPort.ToString());
            Properties.Settings.Default.Context.Remove("timerElapsing");
            Properties.Settings.Default.Context.Add("timerElapsing", timerElapsing.ToString());
            Properties.Settings.Default.Context.Remove("imagesToShow");
            Properties.Settings.Default.Context.Add("imagesToShow", imagesToShow.ToString());
            Properties.Settings.Default.Context.Remove("takenPoints");
            Properties.Settings.Default.Context.Add("takenPoints", takenPoints.ToString());
            Properties.Settings.Default.Context.Remove("directionChangeTresholdXY");
            Properties.Settings.Default.Context.Add("directionChangeTresholdXY", directionChangeTresholdXY.ToString());
            Properties.Settings.Default.Context.Remove("directionChangeTresholdZ");
            Properties.Settings.Default.Context.Add("directionChangeTresholdZ", directionChangeTresholdZ.ToString());

            //Sauvegarde la configuration.
            Properties.Settings.Default.Save();
            Properties.Settings.Default.Reload();
        }

        /*
         * Getters et setters des paramètres du Middleware.
         */
        public void setMinDistHands(float min)
        {
            minDistHands = min;
        }
        public void setMaxDistHands(float max)
        {
            maxDistHands = max;
        }
        public void setMinDist(float min)
        {
            minDist = min;
        }
        public void setMaxDist(float max)
        {
            maxDist = max;
        }
        public void setZeroPoint(float zero)
        {
            zeroPoint = zero;
        }
        public void setConnexionHost(String host)
        {
            connexionHost = host;
        }
        public void setConnexionPort(int port)
        {
            connexionPort = port;
        }
        public void setTimerElapsing(int time)
        {
            timerElapsing = time;
        }
        public void setImagesToShow(int _imagesToShow)
        {
            imagesToShow = _imagesToShow;
        }
        public void setTakenPoints(int _takenPoints)
        {
            takenPoints = _takenPoints;
        }
        public void setDirectionChangeTresholdXY(int _directionChangeTresholdXY)
        {
            directionChangeTresholdXY = _directionChangeTresholdXY;
        }
        public void setDirectionChangeTresholdZ(float _directionChangeTresholdZ)
        {
            directionChangeTresholdZ = _directionChangeTresholdZ;
        }
        public void setSwitch(Button _switch)
        {
            Switch = _switch;
        }
        public void setOn(bool _on)
        {
            on = _on;
        }
        public void setQuitMenu(MenuItem quitMenu)
        {
            QuitMenu = quitMenu;
        }
        public void setParametersWindow(DebugParameters parameters)
        {
            param = parameters;
        }
        public void setParamMenu(MenuItem parameters)
        {
            ParamMenu = parameters;
        }

        public float getMinDistHands()
        {
            return minDistHands;
        }
        public float getMaxDistHands()
        {
            return maxDistHands;
        }
        public float getMinDist()
        {
            return minDist;
        }
        public float getMaxDist()
        {
            return maxDist;
        }
        public float getZeroPoint()
        {
            return zeroPoint;
        }
        public String getConnexionHost()
        {
            return connexionHost;
        }
        public int getConnexionPort()
        {
            return connexionPort;
        }
        public int getTimerElapsing()
        {
            return timerElapsing;
        }
        public int getImagesToShow()
        {
            return imagesToShow;
        }
        public int getTakenPoints()
        {
            return takenPoints;
        }
        public int getDirectionChangeTresholdXY()
        {
            return directionChangeTresholdXY;
        }
        public float getDirectionChangeTresholdZ()
        {
            return directionChangeTresholdZ;
        }
        public Button getSwitch()
        {
            return Switch;
        }
        public bool getOn()
        {
            return on;
        }
        public MenuItem getQuitMenu()
        {
            return QuitMenu;
        }
        public DebugParameters getParametersWindow()
        {
            return param;
        }
        public MenuItem getParamMenu()
        {
            return ParamMenu;
        }

        public void onR0(bool b)
        {
            if(b)
                R0.Fill = System.Windows.Media.Brushes.Blue;
            else
                R0.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR1(bool b)
        {
            if (b)
                R1.Fill = System.Windows.Media.Brushes.Blue;
            else
                R1.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR2(bool b)
        {
            if (b)
                R2.Fill = System.Windows.Media.Brushes.Blue;
            else
                R2.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR3(bool b)
        {
            if (b)
                R3.Fill = System.Windows.Media.Brushes.Blue;
            else
                R3.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR4(bool b)
        {
            if (b)
                R4.Fill = System.Windows.Media.Brushes.Blue;
            else
                R4.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR5(bool b)
        {
            if (b)
                R5.Fill = System.Windows.Media.Brushes.Blue;
            else
                R5.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR6(bool b)
        {
            if (b)
                R6.Fill = System.Windows.Media.Brushes.Blue;
            else
                R6.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR7(bool b)
        {
            if (b)
                R7.Fill = System.Windows.Media.Brushes.Blue;
            else
                R7.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR8(bool b)
        {
            if (b)
                R8.Fill = System.Windows.Media.Brushes.Blue;
            else
                R8.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR9(bool b)
        {
            if (b)
                R9.Fill = System.Windows.Media.Brushes.Blue;
            else
                R9.Fill = System.Windows.Media.Brushes.DarkGray;
        }
        public void onR10(bool b)
        {
            if (b)
                R10.Fill = System.Windows.Media.Brushes.Blue;
            else
                R10.Fill = System.Windows.Media.Brushes.DarkGray;
        }
    }
}
