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

namespace bbiwarg.Recognition.FingerRecognition
{
    class FingerSliceTrail
    {
        private List<FingerSlice> slices;
        private List<Point> pointsA;
        private List<Point> pointsB;
        public FingerSlice StartSlice { get { return slices[0]; } }
        public FingerSlice MidSlice { get { return slices[NumSlices / 2]; } }
        public FingerSlice EndSlice { get { return slices[slices.Count - 1]; } }
        public FingerSlice this[int index] { get { return slices[index]; } }
        public int NumSlices { get { return slices.Count; } }
        public LineSegment2D LineSegment { get; private set; }

        public FingerSliceTrail(FingerSlice slice)
        {
            slices = new List<FingerSlice>();
            pointsA = new List<Point>();
            pointsB = new List<Point>();
            addSlice(slice);
        }

        public void addSlice(FingerSlice slice)
        {
            slices.Add(slice);
            pointsA.Add(slice.Start + Constants.FingerContourMargin * slice.Direction.getInverse());
            pointsB.Add(slice.End + Constants.FingerContourMargin * slice.Direction);
            pointsA.Add(slice.Start);
            createLineSegment();
        }

        private void createLineSegment()
        {
            LineSegment = new LineSegment2D(EndSlice.Mid, StartSlice.Mid);
        }

        public Vector2D getStartDirection()
        {
            int innerStartIndex = Math.Min(NumSlices, Constants.FingerNumSlicesForRelativeDirection);
            return (StartSlice.Mid - slices[innerStartIndex].Mid).normalize();
        }

        public Vector2D getEndDirection()
        {
            int innerEndIndex = Math.Max(0, NumSlices - Constants.FingerNumSlicesForRelativeDirection);
            return (EndSlice.Mid - slices[innerEndIndex].Mid).normalize();
        }

        public void removeFirstSlices(int numSlices)
        {
            slices.RemoveRange(0, numSlices);
            pointsA.RemoveRange(0, numSlices);
            pointsB.RemoveRange(0, numSlices);
            createLineSegment();
        }

        public void reverse() {
            slices.Reverse();
            pointsA.Reverse();
            pointsB.Reverse();

            List<Point> dummy = pointsA;
            pointsA = pointsB;
            pointsB = dummy;

            createLineSegment();
        }



        public Contour<Point> getContour()
        {
            pointsA.Reverse();
            List<Point> points = new List<Point>();
            points.AddRange(pointsA);
            points.AddRange(pointsB);
            pointsA.Reverse();

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