using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;

using bbiwarg.Utility;

namespace bbiwarg
{
    public enum InputType
    {
        Camera,
        Movie
    }

    class Parameters
    {
        // input
        public static readonly InputType InputSource = InputType.Camera;
        public static readonly String InputMoviePath = "..\\..\\videos\\touch\\4.skv";

        // Logger
        public static readonly LogSubject EnabledLogSubjects = LogSubject.None;
        public static readonly int ConsoleWidth = 90;
        public static readonly int ConsoleHeight = 30;

        // Debug window
        public static readonly bool DebugWindowEnabled = true;
        public static readonly int DebugWindowUpdateRate = 30;
        public static readonly int DebugWindowRenderRate = 30;
        public static readonly int DebugWindowNumImages = 5;
        public static readonly int DebugWindowNumImagesPerRow = 3;
        public static readonly float DebugWindowScaleFactor = 1f; // output window size is scaled by this factor (from necessary size for images)
        public static readonly String DebugWindowTitle = "BBIWARG - DebugOutput";

        // glasses window
        public static readonly bool GlassesWindowEnabled = true;
        public static readonly int GlassesWindowUpdateRate = 30;
        public static readonly int GlassesWindowRenderRate = 30;
        public static readonly int GlassesWindowWidth = 1280;
        public static readonly int GlassesWindowHeight = 720;
        public static readonly String GlassesWindowTitle = "BBIWARG - GlassesOutput";

        // TUIO
        public static bool TuioEnabled { get; private set; }
        public static IPAddress TuioIP { get; private set; }
        public static Int16 TuioPort { get; private set; }

        // image
        public static int ImageWidth { get; private set; }
        public static int ImageHeight { get; private set; }
        public static int ImageNumPixels { get; private set; }
        public static Vector2D ImageMaxPixel { get; private set; }
        public static float ImageDiagonalLength { get; private set; }
        public static float ImageAspectRatio { get; private set; }

        // confidence image
        public static readonly int ConfidenceImageMinThreshold = 500;

        // depth image
        public static readonly int DepthImageMedianSize = 5;
        public static readonly int DepthImageDepthRange = 200; // <255

        // edge image
        public static readonly int EdgeImageCannyStartThreshold = 80;
        public static readonly int EdgeImageCannyLinkingThreshold = 60;
        public static readonly int EdgeImageCannySize = 3;
        public static readonly int EdgeImageRoughNumDilationIterations = 1;

        // general tracking
        public static readonly float TrackerMaxRelativeMove = 0.25f;

        // finger detection
        public static readonly int FingerStepSize = 1;
        public static readonly int FingerMaxGapCounter = 3;
        public static readonly int FingerMaxSliceDifferencePerStep = 5;
        public static readonly int FingerMinNumSlices = 25 / FingerStepSize;
        public static readonly int FingerMaxWidth = 30;
        public static readonly int FingerMinWidth = 2;
        public static readonly int FingerRemoveNumSlicesForCorrection = 10 / FingerStepSize;
        public static readonly int FingerNumSlicesForRelativeDirection = FingerRemoveNumSlicesForCorrection;
        public static readonly int FingerOutMargin = 8;
        public static readonly int FingerMaxCrippleDifference = 20;
        public static readonly int FingerContourMargin = 4;

        // finger tracking
        public static readonly int FingerTrackerNumFramesDetectedUntilTracked = 5;
        public static readonly int FingerTrackerNumFramesLostUntilDeleted = 10;
        public static readonly float FingermXX = 0.000005f;
        public static readonly float FingermXY = 0.0f;
        public static readonly float FingermYY = 0.000005f;
        public static readonly int FingerTrackerNumDirectionsForMeanDirection = 10;
        public static readonly float FingerTrackerMaxTipPointRelativeMove = TrackerMaxRelativeMove;
        public static readonly float FingerTrackerMaxHandPointRelativeMove = TrackerMaxRelativeMove;

        // hand detection
        public static readonly int HandNumColors = 3;
        public static readonly int HandFloodFillDownDiff = 2;
        public static readonly int HandFloodFillUpDiff = 2;
        public static readonly float HandMaxSize = 0.6f;
        public static readonly float HandMinSize = 0.01f;
        public static readonly float HandExtensionMaxSize = 0.5f * HandMaxSize;
        public static readonly int HandExtendMaxDifference = 40;
        public static readonly float HandThumbDefectMaxDistanceToThumb = FingerMaxWidth;
        public static readonly float HandThumbDefectMinThumbShortLengthRatio = 0.75f;
        public static readonly float HandThumbDefectMaxThumbShortLengthRatio = 1.1f;
        public static readonly float HandThumbDefectMinShortLongLengthRatio = 0.3f;
        public static readonly float HandThumbDefectMaxShortLongLengthRatio = 0.7f;

        // hand tracker
        public static readonly int HandTrackerNumFramesDetectedUntilTracked = 5;
        public static readonly int HandTrackerNumFramesLostUntilDeleted = 5;
        public static readonly float HandTrackerMaxCentroidRelativeMove = TrackerMaxRelativeMove;
        public static readonly float HandmXX = 0.0005f;
        public static readonly float HandmXY = 0.0f;
        public static readonly float HandmYY = 0.0005f;

        // palm detection
        public static readonly int PalmNumPositionsForPalmWidth = 5;
        public static readonly float PalmInsideTolerance = 0.1f;

        // palm tracker
        public static readonly int PalmTrackerNumFramesDetectedUntilTracked = 5;
        public static readonly int PalmTrackerNumFramesLostUntilDeleted = 5;
        public static readonly float PalmTrackerMaxWristUpperRelativeMove = TrackerMaxRelativeMove;
        public static readonly float PalmTrackerMaxWristLowerRelativeMove = TrackerMaxRelativeMove;
        public static readonly float PalmTrackerMaxFingersUpperRelativeMove = TrackerMaxRelativeMove;
        public static readonly float PalmTrackerMaxFingersLowerRelativeMove = TrackerMaxRelativeMove;
        public static readonly float PalmmXX = 0.00005f;
        public static readonly float PalmmXY = 0.0f;
        public static readonly float PalmmYY = 0.00005f;

        //palm Grid
        public static int PalmGridNumRows { get; private set; }
        public static int PalmGridNumColumns { get; private set; }

        // touch detection
        public static readonly float TouchMinTouchValue = 0.3f;
        public static readonly int TouchAreaSize = 30;
        public static readonly int TouchFloodfillDownDiff = 1;
        public static readonly int TouchFloodfillUpDiff = 3;
        public static readonly int TouchTipInsideFactor = 2;
        public static readonly int TouchTipOutsideFactor = 7;

        // touch tracking
        public static readonly int TouchTrackerNumFramesDetectedUntilTracked = 1;
        public static readonly int TouchTrackerNumFramesLostUntilDeleted = 5;
        public static readonly float TouchTrackerMaxAbsolutePositionRelativeMove = TrackerMaxRelativeMove;
        public static readonly float TouchmXX = 0.003f;
        public static readonly float TouchmXY = 0.0f;
        public static readonly float TouchmYY = 0.00165f;
        public static readonly float TouchProcessNoise = 3.0e-4f;

        // touchEventVisualizer
        public static readonly int TouchEventVisualizerFadeOutTime = 1500;

        // colors
        public static readonly Color ColorDetected = Color.Turquoise;
        public static readonly Color ColorTracked = Color.Yellow;

        public static readonly Color DepthImageColor = Color.White;
        public static readonly Color EdgeImageColor = Color.Blue;
        public static readonly Color OutputImageBorderColor = Color.White;

        public static readonly Color FingerSliceColor = Color.Magenta;
        public static readonly Color FingerDetectedColor = ColorDetected;
        public static readonly Color FingerTrackedColor = ColorTracked;
        public static readonly Color FingerTipColor = Color.Blue;
        public static readonly Color FingerHandColor = Color.Yellow;
        public static readonly Color FingerContourColor = Color.Red;
        public static readonly Color FingerIDColor = Color.White;

        public static readonly Color TouchEventDetectedColor = ColorDetected;
        public static readonly Color TouchEventTrackedColor = ColorTracked;
        public static readonly Color TouchEventAreaMatchedSubtractColor = Color.DarkOrange;
        public static readonly Color TouchEventAreaNonMatchedSubtractColor = Color.DarkSlateGray;
        public static readonly Color TouchEventStatusBarColor = Color.Green;

        public static readonly Color TouchEventVisualizerLineColor = Color.Yellow;
        public static readonly Color TouchEventVisualizerPointColor = Color.Red;
        public static readonly Color TouchEventVisualizerGridColor = Color.White;
        public static readonly Color TouchEventVisualizerTextColor = Color.White;
        public static readonly Color TouchEventVisualizerActiveBlockColor = Color.DarkSlateGray;

        public static readonly Color PalmQuadColor = Color.Blue;
        public static readonly Color PalmGridColor = Color.CornflowerBlue;

        public static readonly Color[] HandColors = new Color[3] { Color.Red, Color.Blue, Color.Green };
        public static readonly Color HandCentroidColor = Color.Yellow;
        public static readonly Color HandIDColor = Color.White;
        public static readonly Color HandThumbDefectPointColor = Color.Lime;
        public static readonly Color HandThumbDefectLineColor = Color.CornflowerBlue;

        static Parameters()
        {
            setImageParameters(320, 240);
            setTuioParameters(true, new IPAddress(new byte[4] { 127, 0, 0, 1 }), 3333);
            setPalmGridParameters(3, 4);
        }

        public static void setImageParameters(int width, int height)
        {
            ImageWidth = width;
            ImageHeight = height;
            ImageNumPixels = ImageWidth * ImageHeight;
            ImageMaxPixel = new Vector2D(ImageWidth - 1, ImageHeight - 1);
            ImageDiagonalLength = ImageMaxPixel.Length;
            ImageAspectRatio = (float)ImageWidth / (float)ImageHeight;
        }

        public static void setTuioParameters(bool enabled, IPAddress ipAddress, Int16 port)
        {
            TuioEnabled = enabled;
            TuioIP = ipAddress;
            TuioPort = port;
        }

        public static void setPalmGridParameters(int numRows, int numColumns)
        {
            PalmGridNumRows = numRows;
            PalmGridNumColumns = numColumns;
        }
    }
}
