using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sensors.Scanners.MicroEpsilon

{
    public interface IscanCONTROL
    {
        #region enum definitions

        #endregion

        #region constants

        #endregion

        #region constructor / destructor

        #endregion

        #region public methods

        /// <summary>Connects to device using Ethernet</summary>
        /// <param name="IPaddress">IP address of device to connect</param>
        /// <returns>returns true if connected successfully</returns>
        bool ConnectETH(string IPaddress);

        /// <summary>Starts continuous measuring process</summary>
        /// <returns>returns true if measuring started successfully</returns>
        bool StartMeas();

        /// <summary>Stops continuous measuring process</summary>
        /// <returns>returns true if measuring stopped successfully</returns>
        bool StopMeas();

        /// <summary>Terminates connection with device</summary>
        /// <returns>returns true if disconnected successfully</returns>
        bool Disconnect();

        /// <summary>Returns measured values (profile data)</summary>
        /// <returns>array of points defined by X and Z coordinates</returns>
        XZpoint[] GetValues();

        #endregion

        #region public parameters

        /// <summary>Returns true if driver is actually connected to device</summary>
        bool Connected { get; }

        /// <summary>Mode of Laser emitter</summary>
        LaserModes LaserPower { get; set; }

        /// <summary>Format of data</summary>
        uint Resolution { get; set; }

        /// <summary>Defines time when shutter is on. Defined in number of 10us, allowed range 1 .. 4095 (eg. 10..40950us)</summary>
        uint ShutterTime { get; set; }

        /// <summary>Defines time when shutter is off. Defined in number of 10us, allowed range 1 .. 4095 (eg. 10..40950us)</summary>
        uint IdleTime { get; set; }

        /// <summary>Threshold for the selection of reflections. At targets with several reflections this may lead to better results.</summary>
        uint ReflectionThreshold { get; set; }

        /// <summary>Enables interpolating of invalid points</summary>
        bool InvalidPointsFilter { get; set; }

        /// <summary>Enables automatic regulation of shutter time depending on scanned object</summary>
        bool AutoShutter { get; set; }

        /// <summary>Sets range of scanning in X axis</summary>
        XRanges XRange { get; set; }

        /// <summary>Enables/disables median filter</summary>
        NumSamples MedianFilter { get; set; }

        /// <summary>Enables/disables average filter</summary>
        NumSamples AverageFilter { get; set; }
        #endregion

        #region static methods

        #endregion

        #region events

        /// <summary>Connected to device</summary>
        event EventHandler OnConnected;

        /// <summary>Disconnected from device</summary>
        event EventHandler OnClosed;

        #endregion
    }
    
    #region enum definitions

    /// <summary>specifies the interface type for CreateLLTDevice and IsInterfaceType</summary>
    public enum InterfaceType
    {
        INTF_TYPE_UNKNOWN = 0,
        INTF_TYPE_SERIAL = 1,
        INTF_TYPE_FIREWIRE = 2,
        INTF_TYPE_ETHERNET = 3
    }

    /// <summary>specify the callback type</summary>
    public enum CallbackType
    {
        STD_CALL = 0,
        C_DECL = 1,
    }

    /// <summary>specify the type of the scanner</summary>
    public enum ScannerType
    {
        StandardType = -1,                    //can't decode scanCONTROL name use standard measurmentrange
        LLT25 = 0,                           //scanCONTROL28xx with 25mm measurmentrange
        LLT100 = 1,                           //scanCONTROL28xx with 100mm measurmentrange

        scanCONTROL28xx_25 = 0,              //scanCONTROL28xx with 25mm measurmentrange
        scanCONTROL28xx_100 = 1,              //scanCONTROL28xx with 100mm measurmentrange
        scanCONTROL28xx_10 = 2,              //scanCONTROL28xx with 10mm measurmentrange
        scanCONTROL28xx_xxx = 999,            //scanCONTROL28xx with no measurmentrange -> use standard measurmentrange

        scanCONTROL27xx_25 = 1000,           //scanCONTROL27xx with 25mm measurmentrange
        scanCONTROL27xx_100 = 1001,           //scanCONTROL27xx with 100mm measurmentrange
        scanCONTROL27xx_50 = 1002,           //scanCONTROL27xx with 50mm measurmentrange
        scanCONTROL2751_25 = 1020,           //scanCONTROL27xx with 25mm measurmentrange
        scanCONTROL2751_100 = 1021,           //scanCONTROL27xx with 100mm measurmentrange
        scanCONTROL2702_50 = 1032,           //scanCONTROL2702 with 50mm measurement range
        scanCONTROL27xx_xxx = 1999,           //scanCONTROL27xx with no measurmentrange -> use standard measurmentrange

        scanCONTROL26xx_25 = 2000,           //scanCONTROL26xx with 25mm measurmentrange
        scanCONTROL26xx_100 = 2001,           //scanCONTROL26xx with 100mm measurmentrange
        scanCONTROL26xx_50 = 2002,           //scanCONTROL26xx with 50mm measurmentrange
        scanCONTROL2651_25 = 2020,           //scanCONTROL26xx with 25mm measurmentrange
        scanCONTROL2651_100 = 2021,           //scanCONTROL26xx with 100mm measurmentrange
        scanCONTROL2602_50 = 2032,           //scanCONTROL2602 with 50mm measurement range
        scanCONTROL26xx_xxx = 2999,           //scanCONTROL26xx with no measurmentrange -> use standard measurmentrange

        scanCONTROL29xx_25 = 3000,           //scanCONTROL29xx with 25mm measurmentrange
        scanCONTROL29xx_100 = 3001,           //scanCONTROL29xx with 100mm measurmentrange
        scanCONTROL29xx_50 = 3002,           //scanCONTROL29xx with 50mm measurmentrange
        scanCONTROL2951_25 = 3020,           //scanCONTROL29xx with 25mm measurmentrange
        scanCONTROL2951_100 = 3021,           //scanCONTROL29xx with 100mm measurmentrange
        scanCONTROL2902_50 = 3032,           //scanCONTROL2902 with 50mm measurement range
        scanCONTROL2953_30 = 3033,           //scanCONTROL2953 with 30mm measurement range
        scanCONTROL29xx_xxx = 3999,           //scanCONTROL29xx with no measurmentrange -> use standard measurmentrange
        scanCONTROL2xxx = 4000,           //scanCONTROL2xxx with 100mm measurmentrange
    }

    /// <summary>specify the profile configuration</summary>
    public enum ProfileConfig
    {
        NONE = 0,
        PROFILE = 1,
        CONTAINER = 1,
        VIDEO_IMAGE = 1,
        PURE_PROFILE = 2,
        QUARTER_PROFILE = 3,
        CSV_PROFILE = 4,
        PARTIAL_PROFILE = 5,
    }

    /// <summary>specify the type for the profile transfer</summary>
    public enum TransferProfileType
    {
        NORMAL_TRANSFER = 0,
        SHOT_TRANSFER = 1,
        NORMAL_CONTAINER_MODE = 2,
        SHOT_CONTAINER_MODE = 3,
        NONE_TRANSFER = 4,
    }

    /// <summary>Available ranges in milimetres of scanning in X axis.</summary>
    public enum XRanges
    {
        PLUSMINUS_4 = 1,
        PLUSMINUS_5 = 2,
        PLUSMINUS_10 = 3,
        PLUSMINUS_20 = 4,
        PLUSMINUS_40 = 5,
        PLUSMINUS_50 = 6,
        PLUSMINUS_100 = 7
    }

    /// <summary>Number of samples for median and average filter</summary>
    public enum NumSamples
    {
        DISABLE_FILTER = 0,
        SAMPLES_3 = 1,
        SAMPLES_5 = 2,
        SAMPLES_7 = 3
    }

    /// <summary>Possible powers of laser source</summary>
    public enum LaserModes
    {
        OFF = 0,
        HALF = 1,
        FULL = 2
    }

    #endregion

    #region class definitions

    /// <summary>structure for storing measured values</summary>
    public class XZpoint
    {
        /// <summary>X coordinate of point</summary>
        public double X { get; set; }
        /// <summary>Z coordinate of point</summary>
        public double Z { get; set; }
        /// <summary>Reflection of laser when point was measured</summary>
        public ushort Reflection { get; set; }
        /// <summary>Width (in pixels) of reflected laser line</summary>
        public ushort ReflectionWidth { get; set; }

        public XZpoint()
        {
            X = 0;
            Z = 0;
            Reflection = 0;
            ReflectionWidth = 0;
        }
        public XZpoint(double x, double z)
        {
            X = x;
            Z = z;
            Reflection = 0;
            ReflectionWidth = 0;
        }
        public XZpoint(double x, double z, ushort reflection, ushort width)
        {
            X = x;
            Z = z;
            Reflection = reflection;
            ReflectionWidth = width;
        }

        /// <summary>Transform point itself by specified parameters</summary>
        public void Transform(double Xoffset, double Zoffset, double Xscale = 1, double Zscale = 1)
        {
            X *= Xscale;
            Z *= Zscale;
            X += Xoffset;
            Z += Zoffset;
        }

        /// <summary>Saturates Z values lower that lowLimit and higher than HighLimit</summary>
        public void SaturateZ(double lowLimit, double highLimit)
        {
            if (Z < lowLimit)
                Z = lowLimit;
            if (Z > highLimit)
                Z = highLimit;
        }

        /// <summary>casting operator from XZpoint to Point</summary>
        public static explicit operator System.Drawing.Point(XZpoint point)
        {
            return new System.Drawing.Point((int)point.X, (int)point.Z);
        }
    }

    #endregion

}
