using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using bbiwarg.Images;
using bbiwarg.Utility;
using Emgu.CV;

namespace bbiwarg.Detectors.FingerDetection
{
    class Finger
    {
        public Vector2D TipPoint { get { return SliceTrail.Start.Mid; } }
        public Vector2D HandPoint { get { return SliceTrail.End.Mid; } }
        public LineSegment2D LineSegment { get { return SliceTrail.LineSegment; } }
        public FingerSliceTrail SliceTrail { get; private set; }

        public Finger(FingerSliceTrail sliceTrail)
        {
            //check direction
            if (sliceTrail.Start.Length > sliceTrail.End.Length)
                sliceTrail.Slices.Reverse();

            SliceTrail = sliceTrail;
        }

        public Contour<Point> getContour()
        {
            List<Point> pointsA = new List<Point>();
            List<Point> pointsB = new List<Point>();
            foreach (FingerSlice slice in SliceTrail.Slices)
            {
                Vector2D direction = (slice.End - slice.Start).normalize();
                pointsA.Add(slice.Start - Constants.FingerContourMargin * direction);
                pointsB.Add(slice.End + Constants.FingerContourMargin * direction);
            }

            pointsA.Reverse();
            pointsA.AddRange(pointsB);

            Contour<Point> contour = new Contour<Point>(new MemStorage());
            foreach (Point p in pointsA)
            {
                contour.Push(p);
            }
            return contour;
        }

        //TODO: redo (not use similarity but actual distances and angle instead)
        public float getSimilarity(Finger compareFinger)
        {
            LineSegment2D compareLineSegment = compareFinger.LineSegment;
            Line2D compareLine = compareLineSegment.Line;

            //thresholds
            float thresholdMaxAngle = (float)(30 * Math.PI / 180); // 30°
            float thresholdMaxParallelDistance = 80;
            float thresholdMaxVerticalDistance = 40;

            //check angle
            float angle = LineSegment.Line.getAngleBetween(compareLine);
            float angleSimilarity = Math.Max(1 - angle / thresholdMaxAngle, 0);

            //check parallel distance
            float parallelDistance = LineSegment.getParallelDistanceTo(compareLineSegment);
            float parallelDistanceSimilarity = Math.Max(1 - parallelDistance / thresholdMaxParallelDistance, 0);

            //check vertical distance
            float verticalDistance = LineSegment.getVerticalDistanceTo(compareLineSegment);
            float verticalDistanceSimilarity = Math.Max(1 - verticalDistance / thresholdMaxVerticalDistance, 0);

            return (angleSimilarity + parallelDistanceSimilarity + verticalDistanceSimilarity) / 3;
        }
    }
}
