using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using bbiwarg.Input.InputHandling;
using bbiwarg.Recognition.FingerRecognition;
using bbiwarg.Recognition.HandRecognition;
using bbiwarg.Recognition.PalmRecognition;
using bbiwarg.Recognition.TouchRecognition;
using Emgu.CV.Structure;
using Emgu.CV;

namespace bbiwarg.Output.DebugOutput
{
    class DebugImages
    {
        private TouchEventVisualizer touchEventVisualizer;

        public List<OutputImage> Images { get; private set; }

        public DebugImages(TouchEventVisualizer touchEventVisualizer)
        {
            Images = new List<OutputImage>();
            this.touchEventVisualizer = touchEventVisualizer;
        }

        public void updateImages(FrameData frameData)
        {
            Images.Clear();

            Images.Add(getDepthImage(frameData));
            Images.Add(getFingerImage(frameData));
            Images.Add(getHandImage(frameData));
            Images.Add(getPalmImage(frameData));
            Images.Add(touchEventVisualizer.getOutputImage());
        }

        private OutputImage getDepthImage(FrameData frameData)
        {
            OutputImage depthImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);

            // background (depth image)
            depthImage.drawImage((frameData.DepthImage.MaxDepth - frameData.DepthImage.MinDepth) - frameData.DepthImage.Image, Parameters.DepthImageColor);

            // finger tips
            foreach (Finger f in frameData.TrackedFingers)
            {
                Color tipColor = (f.Touch != null) ? Parameters.TouchEventDetectedColor : Parameters.FingerTipColor;
                Color handColor = Parameters.FingerHandColor;
                depthImage.fillCircle(f.TipPoint.IntX, f.TipPoint.IntY, 5, tipColor);
                depthImage.fillCircle(f.HandPoint.IntX, f.HandPoint.IntY, 5, handColor);
            }

            // border
            depthImage.drawBorder(Parameters.OutputImageBorderColor);

            return depthImage;
        }

        private OutputImage getFingerImage(FrameData frameData)
        {
            OutputImage fingerImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);

            // background (edge image)
            fingerImage.drawImage(frameData.EdgeImage.Image.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.EdgeImageColor);

            // draw fingers
            foreach (Finger f in frameData.TrackedFingers)
            {
                foreach (FingerSlice slice in f.SliceTrail.Slices)
                    fingerImage.drawLineSegment(slice.LineSegment, Parameters.FingerSliceColor);
                fingerImage.drawContour(f.getContour(Parameters.FingerContourMargin), Parameters.FingerContourColor);
                fingerImage.drawLineSegment(f.LineSegment, Parameters.FingerTrackedColor);
                fingerImage.drawText(f.MidPoint.IntX, f.MidPoint.IntY, f.TrackID.ToString(), Parameters.FingerIDColor);
            }

            //border
            fingerImage.drawBorder(Parameters.OutputImageBorderColor);

            return fingerImage;
        }

        private OutputImage getHandImage(FrameData frameData)
        {
            OutputImage handImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);

            foreach (Hand h in frameData.TrackedHands)
            {

                handImage.drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.HandColors[h.TrackID % Parameters.HandNumColors]);
                handImage.fillCircle(h.Centroid.IntX, h.Centroid.IntY, 5, Parameters.HandCentroidColor);
                handImage.drawText(h.Centroid.IntX, h.Centroid.IntY, h.TrackID.ToString(), Parameters.HandIDColor);

                if (h.Palm != null)
                    handImage.drawDefect(h.Palm.ThumbDefect, Parameters.HandThumbDefectPointColor, Parameters.HandThumbDefectLineColor);
            }

            // border
            handImage.drawBorder(Parameters.OutputImageBorderColor);

            return handImage;
        }

        private OutputImage getPalmImage(FrameData frameData)
        {
            OutputImage palmImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);

            // handMask
            Image<Gray, byte> handMask = new Image<Gray, byte>(Parameters.ImageWidth, Parameters.ImageHeight);
            foreach (Hand h in frameData.TrackedHands)
                handMask = handMask.Or(h.Mask);

            // background
            palmImage.drawImage((frameData.DepthImage.MaxDepth - frameData.DepthImage.MinDepth) - frameData.DepthImage.Image.Or(255 - handMask.ThresholdBinary(new Gray(0), new Gray(255))), Parameters.DepthImageColor);
            foreach (Touch t in frameData.TrackedTouches)
                palmImage.fillCircle(t.AbsolutePosition.IntX, t.AbsolutePosition.IntY, 5, Parameters.TouchEventTrackedColor);

            foreach (Palm p in frameData.TrackedPalms)
                palmImage.drawQuadrangleGrid(p.Quad, Parameters.PalmQuadColor, Parameters.PalmGridColor, Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns);
            
            // border
            palmImage.drawBorder(Parameters.OutputImageBorderColor);

            return palmImage;
        }
    }
}

/*
            
//image3
OutputImages[3].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image.Or(255 - handDetector.HandMask.ThresholdBinary(new Gray(0), new Gray(255))), Parameters.DepthImageColor);
foreach (TrackedTouch tte in touchTracker.TrackedObjects)
{
    Vector2D position = tte.AbsolutePositionPrediction;
    OutputImages[3].fillCircle(position.IntX, position.IntY, 5, Parameters.TouchEventTrackedColor);
}
foreach (Palm p in palmTracker.OptimizedPalms)
{
    OutputImages[3].drawQuadrangleGrid(p.Quad, Parameters.PalmQuadColor, Parameters.PalmGridColor, Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns);
}

//image4
touchEventVisualizer.updateImage();
OutputImages[4] = touchEventVisualizer.OutputImage;

//borders
for (int i = 0; i < numImages; i++)
{
    OutputImages[i].drawRectangle(0, 0, Parameters.ImageWidth - 1, Parameters.ImageHeight - 1, Parameters.OutputImageBorderColor);
}

}

}
}
*/