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 bbiwarg.Graphics;
using bbiwarg.Recognition.HandRecognition;
using bbiwarg.Recognition.Tracking;
using Emgu.CV;

namespace bbiwarg.Recognition.FingerRecognition
{
    class Finger : TrackableObject
    {
        public Vector2D TipPoint { get { return SliceTrail.StartSlice.Mid; } }
        public Vector2D HandPoint { get { return SliceTrail.EndSlice.Mid; } }
        public Vector2D MidPoint { get { return SliceTrail.MidSlice.Mid; } }
        public Vector2D Direction { get { return LineSegment.Direction; } }
        public Vector2D TipDirection { get { return SliceTrail.getStartDirection(); } }
        public Vector2D HandDirection { get { return SliceTrail.getEndDirection(); } }
        public LineSegment2D LineSegment { get { return SliceTrail.LineSegment; } }
        public FingerSliceTrail SliceTrail { get; private set; }
        public Contour<Point> Contour { get { return SliceTrail.getContour(); } }

        public Finger(FingerSliceTrail sliceTrail)
            : base()
        {
            SliceTrail = sliceTrail;
        }

        public override float getSimilarity(TrackableObject compareObject)
        {
            Finger compareFinger = (Finger)compareObject;
            LineSegment2D compareLineSegment = compareFinger.LineSegment;
            Line2D compareLine = compareLineSegment.Line;
            
            //tip position
            float tipPointDistance = TipPoint.getDistanceTo(compareFinger.TipPoint);
            float tipPointSimilarity = Math.Max(0, 1 - tipPointDistance / Constants.FingerSimilarityMaxTipPointDistance);

            //hand position
            float handPointDistance = HandPoint.getDistanceTo(compareFinger.HandPoint);
            float handPointSimilarity = Math.Max(0, 1 - handPointDistance / Constants.FingerSimilarityMaxHandPointDistance);
            /*
            //check angle
            float angle = LineSegment.Line.getAngleBetween(compareLine);
            float angleSimilarity = Math.Max(1 - angle / Constants.FingerSimilarityMaxAngle, 0);

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

            //check vertical distance
            float verticalDistance = LineSegment.getVerticalDistanceTo(compareLineSegment);
            float verticalDistanceSimilarity = Math.Max(1 - verticalDistance / Constants.FingerSimilarityMaxVerticalDistance, 0);
            */
            float similarity = tipPointSimilarity * handPointSimilarity;
            //float similarity = tipPointSimilarity * handPointSimilarity * angleSimilarity * parallelDistanceSimilarity * verticalDistanceSimilarity;
            //float similarity = (tipPointSimilarity + handPointSimilarity + angleSimilarity + parallelDistanceSimilarity + verticalDistanceSimilarity)/5;
            //float similarity = (angleSimilarity + parallelDistanceSimilarity + verticalDistanceSimilarity) / 3;

            return similarity;
        }

        public void draw(OutputImage outputImage, bool tracked)
        {
            if (tracked)
            {
                outputImage.drawLineSegment(LineSegment, Constants.FingerTrackedColor);
            }
            else
            {
                for (int i = 0; i < SliceTrail.NumSlices; i++)
                {
                    outputImage.drawLineSegment(SliceTrail[i].LineSegment, Constants.FingerSliceColor);
                }
                outputImage.drawLineSegment(LineSegment, Constants.FingerDetectedColor);
                outputImage.drawContour(Contour, Constants.FingerContourColor, 1);
            }
        }
    }
}
