using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;

namespace GestureControl
{
    /// <summary>
    /// Take a list of points and try to recognize a pattern
    /// </summary>
    public class SurfaceGesture : List<SurfaceGestureVector>
    {

        #region Prop
        /// <summary>
        /// Allow some variation without log a direction
        /// </summary>
        public int Precision { get; set; }
        #endregion

        #region Constructor
        /// <summary>
        /// load know patterns and generate the vector list from a list of points with a default 20 precision factor
        /// </summary>
        /// <param name="list"></param>
        public SurfaceGesture(List<SurfaceGesturePoint> list)
        {
            this.Precision = 20;
            this.Generate(list);
        }
        /// <summary>
        /// load know patterns and generate the vector list from a list of points with a precision factor
        /// </summary>
        /// <param name="list"></param>
        /// <param name="precision"></param>
        public SurfaceGesture(List<SurfaceGesturePoint> list, int precision)
        {
            this.Precision = 20;
            this.Generate(list);
        }
        #endregion

        #region GenerateVector
        /// <summary>
        /// Generate list of vector from courbe mouvements, filter with the pas value
        /// </summary>
        /// <param name="list"></param>
        /// <param name="pas"></param>
        /// <returns></returns>
        private bool GenerateCourb(List<SurfaceGesturePoint> list, int pas)
        {
            int sep = list.Count / pas;
            double count = 0; ;
            SurfaceGesturePoint past = new SurfaceGesturePoint() { X = 0, Y = 0 };
            double y = 0;

            for (int i = 0; i < list.Count - 1; i++)
            {
                if (i % pas != 0)
                {
                    count += Math.Atan(list[i + 1].Y / list[i + 1].X) - Math.Atan(list[i].Y / list[i].X);
                }
                else
                {
                    count /= pas;
                    if (count == 0 || this.GetDistancePoints(past, list[i + 1]) < 5)
                    {
                        y = list[i + 1].Y;
                        past.X = count;
                        continue;
                    }
                    if (y > list[i + 1].Y)
                    {
                        if (past.X > count)
                            this.AddDirection(SurfaceGestureVectorDirection.UPRIGHT);
                        else
                            this.AddDirection(SurfaceGestureVectorDirection.UPLEFT);
                    }
                    else
                    {
                        if (past.X > count)
                            this.AddDirection(SurfaceGestureVectorDirection.DOWNRIGHT);
                        else
                            this.AddDirection(SurfaceGestureVectorDirection.DOWNLEFT);
                    }
                    y = list[i + 1].Y;
                    past.X = count;
                }
            }
            Console.Write(this);
            /*if (this.GetPattern() != "None")
                return true;
            else*/
                return false;
        }
        /// <summary>
        /// Get distance between two points
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        private int GetDistancePoints(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
        {
            return (int)Math.Sqrt(Math.Pow((p2.X - p1.X), 2) + Math.Pow((p1.Y - p2.Y), 2));
        }
        /// <summary>
        /// add a direction in the vector list if past who not the same
        /// </summary>
        /// <param name="type"></param>
        private void AddDirection(SurfaceGestureVectorDirection type)
        {
            if (this.Count == 0)
            {
                this.Add(new SurfaceGestureVector { Direction = type, Lenght = 42 });
                return;
            }
            if (this[this.Count - 1].Direction != type)
                this.Add(new SurfaceGestureVector { Direction = type, Lenght = 42 });
        }
        /// <summary>
        /// generate list of vector
        /// </summary>
        /// <param name="list"></param>
        private void Generate(List<SurfaceGesturePoint> list)
        {            
            SurfaceGestureVectorDirection lastDirection = SurfaceGestureVectorDirection.NONE;
            int lastPoint = 0;
            SurfaceGesturePoint LastChange = list[0];

            /////// TEST///////////
            if (this.GenerateCourb(list, 5) == true)
                return;
            this.Clear();
            ///////////////////////

            for (int i = 0; i < list.Count - 1; i++)
            {
                if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UP && lastDirection != SurfaceGestureVectorDirection.UP)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.UP;
                }
                else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWN && lastDirection != SurfaceGestureVectorDirection.DOWN)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.DOWN;
                }
                else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UPLEFT && lastDirection != SurfaceGestureVectorDirection.UPLEFT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.UPLEFT;
                }
                else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UPRIGHT && lastDirection != SurfaceGestureVectorDirection.UPRIGHT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.UPRIGHT;
                }
                else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWNLEFT && lastDirection != SurfaceGestureVectorDirection.DOWNLEFT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.DOWNLEFT;
                }
                else if (GetHorizontal(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWNRIGHT && lastDirection != SurfaceGestureVectorDirection.DOWNRIGHT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.DOWNRIGHT;
                }
                else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.LEFT && lastDirection != SurfaceGestureVectorDirection.LEFT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = (Math.Abs(LastChange.X - list[i + 1].X)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.LEFT;
                }
                else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.RIGHT && lastDirection != SurfaceGestureVectorDirection.RIGHT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = (Math.Abs(LastChange.X - list[i + 1].X)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.RIGHT;
                }
                else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UPLEFT && lastDirection != SurfaceGestureVectorDirection.UPLEFT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.UPLEFT;
                }
                else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.UPRIGHT && lastDirection != SurfaceGestureVectorDirection.UPRIGHT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.UPRIGHT;
                }
                else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWNLEFT && lastDirection != SurfaceGestureVectorDirection.DOWNLEFT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.DOWNLEFT;
                }
                else if (GetVertical(list[lastPoint], list[i + 1]) == SurfaceGestureVectorDirection.DOWNRIGHT && lastDirection != SurfaceGestureVectorDirection.DOWNRIGHT)
                {
                    this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = (Math.Abs(LastChange.Y - list[i + 1].Y)), Origin = list[lastPoint] });
                    LastChange = list[i + 1];
                    lastDirection = SurfaceGestureVectorDirection.DOWNRIGHT;
                }
                ++lastPoint;
            }

            //  Analyse des extrémités de la gesture
            /*

            double diffX = Math.Abs(list[0].X - list[list.Count - 1].X);
            double diffY = Math.Abs(list[0].Y - list[list.Count - 1].Y);

            if (diffX < 10 && diffY > 10)
            {
                this.Clear();
                if (up > down)
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up });
                else
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down });
            }
            else if (diffY < 10 && diffX > 10)
            {
                this.Clear();
                if (left > right)
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left });
                else
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right });
            }

            */

            //  Analyse détaillée de la gesture

            List<SurfaceGestureVector> ThisTemp = new List<SurfaceGestureVector>();
            List<SurfaceGestureVector> temp = new List<SurfaceGestureVector>();
            List<SurfaceGestureVector> Tempo = new List<SurfaceGestureVector>();

            if ((this.Count / 10) >= 1)
            {
                /*
                for (int i = 1; i < this.Count + 1; i++)
                {
                    temp.Add(this[i-1]);
                    if (i % 7 == 0)
                    {
                        SurfaceGestureVector result = Analyse(temp);
                        if (ThisTemp.Count == 0 || !ThisTemp[ThisTemp.Count - 1].Direction.Equals(result.Direction))
                            ThisTemp.Add(result);
                        else
                            ThisTemp[ThisTemp.Count - 1].Lenght += result.Lenght;
                        temp.Clear();
                    }
                }
                if (temp.Count > 0)
                {
                    SurfaceGestureVector result = Analyse(temp);
                    if (ThisTemp[ThisTemp.Count - 1].Direction.Equals(result.Direction))
                        ThisTemp[ThisTemp.Count - 1].Lenght += result.Lenght;
                    else
                        ThisTemp.Add(result);
                    temp.Clear();
                }
                this.Clear();
                foreach(SurfaceGestureVector elt in ThisTemp)
                    this.Add(elt);
                 */
                switch (this.Count / 10)
                {
                    case 1:
                        ThisTemp.Add(Analyse(this));
                        this.Clear();
                        if (ThisTemp.Count > 1)
                        {
                            double up = 0, down = 0, left = 0, right = 0, upleft = 0, upright = 0, downleft = 0, downright = 0;
                            foreach (SurfaceGestureVector elt in ThisTemp)
                            {
                                switch (elt.Direction)
                                {
                                    case SurfaceGestureVectorDirection.DOWN:
                                        down += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.DOWNLEFT:
                                        downleft += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.DOWNRIGHT:
                                        downright += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.LEFT:
                                        left += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.RIGHT:
                                        right += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.UP:
                                        up += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.UPLEFT:
                                        upleft += elt.Lenght;
                                        break;
                                    case SurfaceGestureVectorDirection.UPRIGHT:
                                        upright += elt.Lenght;
                                        break;
                                    default:
                                        break;
                                }
                            }
                            if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(up))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upleft))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upright))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(down))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downleft))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downright))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = downright, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(left))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = null });
                            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(right))
                                this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = null });
                        }
                        else
                            this.Add(ThisTemp[0]);
                        break;
                    case 2:
                        for (int index = 1; index <= this.Count; index++)
                        {
                            if (index == this.Count / 2 || index == this.Count)
                            {
                                ThisTemp.Add(Analyse(temp));
                                if (ThisTemp.Count > 1)
                                {
                                    double up = 0, down = 0, left = 0, right = 0, upleft = 0, upright = 0, downleft = 0, downright = 0;
                                    foreach (SurfaceGestureVector elt in ThisTemp)
                                    {

                                        switch (elt.Direction)
                                        {
                                            case SurfaceGestureVectorDirection.DOWN:
                                                down += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.DOWNLEFT:
                                                downleft += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.DOWNRIGHT:
                                                downright += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.LEFT:
                                                left += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.RIGHT:
                                                right += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UP:
                                                up += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UPLEFT:
                                                upleft += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UPRIGHT:
                                                upright += elt.Lenght;
                                                break;
                                        }
                                    }
                                    if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(up))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upleft))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upright))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(down))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downleft))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downright))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = downright, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(left))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(right))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = null });
                                }
                                else
                                    Tempo.Add(ThisTemp[0]);
                            }
                            else
                                ThisTemp.Add(this[index]);
                        }
                        this.Clear();
                        if (Tempo[0].Direction.Equals(Tempo[1].Direction))
                            this.Add(Tempo[0]);
                        else
                            foreach (SurfaceGestureVector elt in Tempo)
                                this.Add(elt);
                        break;
                    case 3:
                        for (int index = 1; index <= this.Count; index++)
                        {
                            if (index == this.Count / 3 || index == this.Count)
                            {
                                ThisTemp.Add(Analyse(temp));
                                if (ThisTemp.Count > 1)
                                {
                                    double up = 0, down = 0, left = 0, right = 0, upleft = 0, upright = 0, downleft = 0, downright = 0;
                                    foreach (SurfaceGestureVector elt in ThisTemp)
                                    {

                                        switch (elt.Direction)
                                        {
                                            case SurfaceGestureVectorDirection.DOWN:
                                                down += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.DOWNLEFT:
                                                downleft += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.DOWNRIGHT:
                                                downright += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.LEFT:
                                                left += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.RIGHT:
                                                right += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UP:
                                                up += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UPLEFT:
                                                upleft += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UPRIGHT:
                                                upright += elt.Lenght;
                                                break;
                                        }
                                    }
                                    if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(up))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upleft))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upright))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(down))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downleft))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downright))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = downright, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(left))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(right))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = null });
                                }
                                else
                                    Tempo.Add(ThisTemp[0]);
                            }
                            else
                                ThisTemp.Add(this[index]);
                        }
                        this.Clear();
                        if (Tempo[0].Direction.Equals(Tempo[1].Direction) && Tempo[0].Direction.Equals(Tempo[2].Direction))
                            this.Add(Tempo[0]);
                        else
                            foreach (SurfaceGestureVector elt in Tempo)
                                this.Add(elt);
                        break;
                    default:
                        for (int index = 1; index <= this.Count; index++)
                        {
                            if (index == this.Count / 4 || index == this.Count)
                            {
                                ThisTemp.Add(Analyse(temp));
                                if (ThisTemp.Count > 1)
                                {
                                    double up = 0, down = 0, left = 0, right = 0, upleft = 0, upright = 0, downleft = 0, downright = 0;
                                    foreach (SurfaceGestureVector elt in ThisTemp)
                                    {

                                        switch (elt.Direction)
                                        {
                                            case SurfaceGestureVectorDirection.DOWN:
                                                down += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.DOWNLEFT:
                                                downleft += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.DOWNRIGHT:
                                                downright += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.LEFT:
                                                left += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.RIGHT:
                                                right += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UP:
                                                up += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UPLEFT:
                                                upleft += elt.Lenght;
                                                break;
                                            case SurfaceGestureVectorDirection.UPRIGHT:
                                                upright += elt.Lenght;
                                                break;
                                        }
                                    }
                                    if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(up))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upleft))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upright))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(down))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downleft))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downright))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = downright, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(left))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = null });
                                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(right))
                                        Tempo.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = null });
                                }
                                else
                                    Tempo.Add(ThisTemp[0]);
                            }
                            else
                                ThisTemp.Add(this[index]);
                        }
                        this.Clear();
                        if (Tempo[0].Direction.Equals(Tempo[1].Direction) && Tempo[0].Direction.Equals(Tempo[2].Direction) && Tempo[0].Direction.Equals(Tempo[3].Direction))
                            this.Add(Tempo[0]);
                        else
                            foreach (SurfaceGestureVector elt in Tempo)
                                this.Add(elt);
                        break;
                }
            }
            else
            {
                ThisTemp.Add(Analyse(this));
                this.Clear();
                if (ThisTemp.Count > 1)
                {
                    double up = 0, down = 0, left = 0, right = 0, upleft = 0, upright = 0, downleft = 0, downright = 0;
                    foreach (SurfaceGestureVector elt in ThisTemp)
                    {

                        switch (elt.Direction)
                        {
                            case SurfaceGestureVectorDirection.DOWN:
                                down += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.DOWNLEFT:
                                downleft += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.DOWNRIGHT:
                                downright += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.LEFT:
                                left += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.RIGHT:
                                right += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.UP:
                                up += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.UPLEFT:
                                upleft += elt.Lenght;
                                break;
                            case SurfaceGestureVectorDirection.UPRIGHT:
                                upright += elt.Lenght;
                                break;
                        }
                    }
                    if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(up))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upleft))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upright))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(down))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downleft))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downright))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = downright, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(left))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = null });
                    else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(right))
                        this.Add(new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = null });
                }
                else
                    this.Add(ThisTemp[0]);
            }
        }

        private SurfaceGestureVector Analyse(List<SurfaceGestureVector> list)
        {
            //  Analyse de la forme
            
            double up = 0, down = 0, left = 0, right = 0, upleft = 0, upright = 0, downleft = 0, downright = 0;
            foreach (SurfaceGestureVector elt in list)
            {

                switch (elt.Direction)
                {
                    case SurfaceGestureVectorDirection.DOWN:
                        down += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.DOWNLEFT:
                        downleft += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.DOWNRIGHT:
                        downright += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.LEFT:
                        left += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.RIGHT:
                        right += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.UP:
                        up += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.UPLEFT:
                        upleft += elt.Lenght;
                        break;
                    case SurfaceGestureVectorDirection.UPRIGHT:
                        upright += elt.Lenght;
                        break;
                }
            }
            /*
            //double cupleft = 0, cupright = 0, cdownleft = 0, cdownright = 0;

            
            if (list.Count > 2)
            {
                double min = 180;
                for (int i = 1; i < list.Count - 2; i++)
                {
                    double a = GetDistancePoints(list[list.Count - 1].Origin, list[0].Origin);
                    double b = GetDistancePoints(list[i].Origin, list[0].Origin);
                    double c = GetDistancePoints(list[i].Origin, list[list.Count - 1].Origin);
                    double angle = 180 * (Math.Acos((b * b + c * c - a * a) / (2 * b * c))) / Math.PI ;
                    min = Math.Min(angle > 0 ? angle : 180, min);
                }
                if(min<130)
                    return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.NONE, Lenght = up, Origin = list[0].Origin };
            }

            if (up < 4 && upleft < 4 && upright < 4 && down < 4 && downleft < 4 && downright < 4 && right < 4 && left < 4)
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.TAP, Lenght = 0 };
            if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(up))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upleft))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(upright))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(down))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downleft))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(downright))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNRIGHT, Lenght = downright, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(left))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = list[0].Origin };
            else if (Math.Max(up, Math.Max(upleft, Math.Max(upright, Math.Max(down, Math.Max(downleft, Math.Max(left, Math.Max(downright, right))))))).Equals(right))
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = list[0].Origin };
            else
                return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.NONE, Lenght = 0, Origin = list[0].Origin });
             */

            double diffX = Math.Abs(list[0].Origin.X - list[list.Count - 1].Origin.X);
            double diffY = Math.Abs(list[0].Origin.Y - list[list.Count - 1].Origin.Y);

            if (diffX < 10 && diffY > 10)
            {
                if (list[0].Origin.Y > list[list.Count - 1].Origin.Y)
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UP, Lenght = up, Origin = list[0].Origin });
                else
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWN, Lenght = down, Origin = list[0].Origin });
            }
            else if (diffY < 10 && diffX > 10)
            {
                if (list[list.Count - 1].Origin.X > list[0].Origin.X)
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.LEFT, Lenght = left, Origin = list[0].Origin });
                else
                    return (new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.RIGHT, Lenght = right, Origin = list[0].Origin });
            }
            else if (diffX > 10 && diffY > 10)
            {
                if (list[0].Origin.Y > list[list.Count - 1].Origin.Y && list[list.Count - 1].Origin.X > list[0].Origin.X)
                    return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPLEFT, Lenght = upleft, Origin = list[0].Origin };
                else if (list[0].Origin.Y > list[list.Count - 1].Origin.Y && list[list.Count - 1].Origin.X < list[0].Origin.X)
                    return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = list[0].Origin };
                else if (list[0].Origin.Y < list[list.Count - 1].Origin.Y && list[list.Count - 1].Origin.X > list[0].Origin.X)
                    return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.DOWNLEFT, Lenght = downleft, Origin = list[0].Origin };
                else
                    return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.UPRIGHT, Lenght = upright, Origin = list[0].Origin };
            }
            else
                return new SurfaceGestureVector { Direction = SurfaceGestureVectorDirection.TAP, Lenght = 0 };
        }

        private SurfaceGestureVectorDirection GetHorizontal(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
        {
            if (p1.Y < p2.Y)
            {
                // go up
                if (Math.Abs(p2.Y - p1.Y) > this.Precision)
                {
                    if (Math.Abs(p2.X - p1.X) < Math.Abs(p2.Y - p1.Y))
                        return SurfaceGestureVectorDirection.DOWN;
                    else
                    {
                        if (p1.X < p2.X)
                            return SurfaceGestureVectorDirection.DOWNRIGHT;
                        else
                            return SurfaceGestureVectorDirection.DOWNLEFT;
                    }
                }
                    else
                    {
                        if (p1.X < p2.X)
                            return SurfaceGestureVectorDirection.DOWNRIGHT;
                        else
                            return SurfaceGestureVectorDirection.DOWNLEFT;
                    }
            }
            else
            {
                // go down
                if (Math.Abs(p1.Y - p2.Y) > this.Precision)
                {
                    if (Math.Abs(p1.X - p2.X) < Math.Abs(p1.Y - p2.Y))
                        return SurfaceGestureVectorDirection.UP;
                    else
                    {
                        if (p1.X < p2.X)
                            return SurfaceGestureVectorDirection.UPRIGHT;
                        else
                            return SurfaceGestureVectorDirection.UPLEFT;
                    }
                }
                else
                {
                    if (p1.X < p2.X)
                        return SurfaceGestureVectorDirection.UPRIGHT;
                    else
                        return SurfaceGestureVectorDirection.UPLEFT;
                }
            }
        }

        private SurfaceGestureVectorDirection GetVertical(SurfaceGesturePoint p1, SurfaceGesturePoint p2)
        {
            if (p1.X < p2.X)
            {
                // go left
                if (Math.Abs(p2.X - p1.X) > this.Precision)
                {
                    if (Math.Abs(p2.Y - p1.Y) < Math.Abs(p2.X - p1.X))
                        return SurfaceGestureVectorDirection.RIGHT;
                    else
                    {
                        if (p1.Y < p2.Y)
                            return SurfaceGestureVectorDirection.DOWNRIGHT;
                        else
                            return SurfaceGestureVectorDirection.UPRIGHT;
                    }
                }
                else
                {
                    if (p1.Y < p2.Y)
                        return SurfaceGestureVectorDirection.DOWNRIGHT;
                    else
                        return SurfaceGestureVectorDirection.UPRIGHT;
                }
            }
            else
            {
                // go right
                if (Math.Abs(p1.X - p2.X) > this.Precision)
                {
                    if (Math.Abs(p1.Y - p2.Y) < Math.Abs(p1.X - p2.X))
                        return SurfaceGestureVectorDirection.LEFT;
                    else
                    {
                        if (p1.Y < p2.Y)
                            return SurfaceGestureVectorDirection.DOWNLEFT;
                        else
                            return SurfaceGestureVectorDirection.UPLEFT;
                    }
                }
                else
                {
                    if (p1.Y < p2.Y)
                        return SurfaceGestureVectorDirection.DOWNLEFT;
                    else
                        return SurfaceGestureVectorDirection.UPLEFT;
                }
            }
        }

        #endregion

        #region Override
        public override String ToString()
        {
            String ret = "";

            foreach (SurfaceGestureVector v in this)
            {
                ret += (v.Direction + ", lenght:" + v.Lenght + ", precision:" + this.Precision + "\n");
                //Console.WriteLine(v.Direction + ", lenght:" + v.Lenght + ", precision:" + this.Precision);
            }
            return ret;
        }
        #endregion
    }
}
