using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace CSharpEloPubInterface
{
 
    [Flags]
    public enum GETPOINTS_STATUS 
    {
	    InitialTouch= 0x00000001,
	    StreamTouch = 0x00000002,
	    UnTouch =     0x00000004
    }

    [Flags]
    public enum VrtlBoundMode
    {
	    enumVrtlDeskDisabled    = 0x00000000,	// no virtual desktop
	    enumVrtlNoBounds        = 0x00000001,	// NO virtual desktop bounds, No Clipping, Cursor visible
	    enumVrtlBoundsClipped   = 0x00000002,   // virtual desktop bounds enable, Clipping, Cursor moves at bounds
	    enumVrtlBoundsFreeze	= 0x00000003	// virtual desktop bounds enable, Clipping, Cursor Freezes at bounds
    }
    
    [Flags]
    public enum APR_PREFERENCES
    {
	    APR_Gaming      = 0x000000000,
	    APR_Signature   = 0x000000001,
	    APR_General     = 0x000000002,
	    APR_POS         = 0x000000003,
	    APR_Custom	    = 0x000000004 // used by EloGetAprPreference only, indicating a customized settings in use.
    }

    [Flags]
    public enum GETPOINTS_CODE	// the blocked call returns data depending on this flag
    {
	    NoRequest               = 0x00000000,
	    ReturnImmediately       = 0x00000001,
 	    ReturnOnTouch           = 0x00000002,
 	    ReturnOnUntouch         = 0x00000003,
 	    ReturnOnNextValidTouch  = 0x00000004,
	    LVS_STREAM              = 0x00000005, 
	    LVS_AUDIO_OVERLOAD      = 0x00000006,
	    LVS_AUDIO_LOWSCORE      = 0x00000007,
	    LVS_AUDIO_HIVARIANCE    = 0x00000008,
	    LVS_INIT                = 0x00000009
    }

    [Flags]
    public enum CONTRL_STAT				// ctrl_status values
    {
	    CS_OK                   = 0x00000000,
	    CS_ConstantTouch        = 0x00000001,
	    CS_CanNotFindController = 0x00000002,
	    CS_NoResponse           = 0x00000003,
	    CS_InvalidResponse      = 0x00000004,
	    CS_CanNotSetBaudRate    = 0x00000005,
	    CS_CommandNotSent       = 0x00000006,
	    CS_SystemError          = 0x00000007,
	    CS_InvalidCommPort      = 0x00000008,
	    CS_CommPortFailedOpen   = 0x00000009,
	    CS_CommPortCommandError = 0x00000010,
	    CS_CommPortNoController = 0x00000011,
	    CS_UndefinedController  = 0x00000012
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ClippingBounds		// IN Set calibrate data input buffer
    {
	    public Int32			X_Max;
	    public Int32			X_Min;
	    public Int32			Y_Max;
	    public Int32			Y_Min;
	    public Int32			Z_Max;
	    public Int32			Z_Min;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct EDGE_ACCEL
    {        
        private const int EDGE_ACCEL_SIZE = 1;
	    public UInt32			Enable;
	    public UInt32			Scale;        
        [MarshalAs(UnmanagedType.Struct, SizeConst=EDGE_ACCEL_SIZE)]
	    public ClippingBounds	Bounds;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct TOUCH_BOUNDARY
    {
	    public ClippingBounds	Bounds;
	    public VrtlBoundMode   ClippingMode;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct TOUCH_POINT
    { 
        public Int32 x; 
        public Int32 y; 
        public Int32 z; 
        public GETPOINTS_STATUS Status;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct QUICK_TOUCH
    {
	    public UInt32	bEnable ;		
	    public UInt32	Dx ;
	    public UInt32	Dy ;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct BEEP
    {
	    public Int32    BeepFlag;
	    public UInt32   BeepFreq ;
	    public UInt32   BeepTime ;
        public Int32    UseExternalSpeaker;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct DRAG_DELAY
    {
	    public UInt32   MinDragDelay ;
	    public UInt32   MaxDragDelay ;
	    public UInt32   DragDelay ;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct RIGHT_BUTTON
    {
	    public UInt32	RightClickHW ;
	    public UInt32	InitialTimeout ;
	    public UInt32	DefaultRightClickDelay ;
	    public UInt32	MaxRightClickDelay ;
	    public UInt32	MinRightClickDelay ; 
	    public UInt32	ClickCount;
	    public UInt32	Active ;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct  UNTOUCH_TIMEOUT
    {
	    public UInt32 	TimeOut;
	    public UInt32	Width;
	    public UInt32	Height;
    } 
    
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public Int32  x;
        public Int32  y;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CALIBRATION		
    {
  	    public Int32			EloDx;
	    public Int32			ScrDx;
	    public Int32			X_Offset;
	    public Int32			EloDy;
	    public Int32			ScrDy;
	    public Int32			Y_Offset;
	    public Int32			EloDz;
	    public Int32			ScrDz;
	    public Int32			Z_Offset;
	    public UInt32			WindowsMonitorNumber ;
	    public UInt32			xyswap;	
	    public Int32			xRes ;		// x, y monitor resolution at which these calculations were made
	    public Int32			yRes ;
	    public Int32			xVirtScrSize ;	// Width and height, in pixels, of the virtual screen. 
	    public Int32			yVirtScrSize ;	// The virtual screen is the bounding rectangle of all display monitors.
	    public Int32			xVirtScrCoord ;	// Coordinates for the left side and the top of the virtual screen. 
	    public Int32			yVirtScrCoord ;	
	    public Int32			xMonLocn ;		// monitor location
	    public Int32			yMonLocn ;

	    public Int32    VDeskMode ;
	    public Int32    nScreenIndex;
        
        private const int CALIB_TOUCH_SIZE = 3;        
        [MarshalAs(UnmanagedType.Struct, SizeConst=CALIB_TOUCH_SIZE)]
	    public POINT    xyTouch;
        [MarshalAs(UnmanagedType.Struct, SizeConst=CALIB_TOUCH_SIZE)]
	    public POINT    xyTarget;
    } 

    [StructLayout(LayoutKind.Sequential)]
    public struct SCREEN_PROPERTIES
    {
        private const int COMPORT_NAME_LENGTH = 256;
	    public Int32		iWindowsMonNo ;
	    public UInt32	Type;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = COMPORT_NAME_LENGTH)] // unicode
        public String Port;

        private const int SERIALNUMBER_NAME_LENGTH = 18;	    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=SERIALNUMBER_NAME_LENGTH)] // the rest is ansi
        public String SerialNumber;
	    public UInt32   HardwareHandshaking ; 
	    public CONTRL_STAT		ctrl_status;	
	    public Int32			BaudRate;
        public SByte crevminor;
        public SByte crevmajor;
        public SByte trevminor;
        public SByte trevmajor;		
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)] 
        public String diagcodes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)] 
        public String id;	
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)] 
        public String cnt_id;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] 
        public String driver_id;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct NVRAM_CAL_DATA
    {
	    public UInt32 dwEDID; // 4-byte serial number in monitor's EDID (Extended Display Identification Data)

	    public Int32 nEloDx;   
	    public Int32 nEloDy;
	    public Int32 nScreenDx;
	    public Int32 nScreenDy;
	    public Int32 nOffsetX;
	    public Int32 nOffsetY;
	    public Int32 bSwapXY;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct CLIP_RECT
    {
	    public Int32			MonitorNumber ;
	    public UInt32			NumBounds;
        
        [MarshalAs(UnmanagedType.Struct, SizeConst=64)]
	    public ClippingBounds	Bounds;
	    public UInt32			ExclusionFlag;
	    public VrtlBoundMode   ClippingMode;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SMARTSET_DATA
    {
	    public Int32 ScreenNumber;
	    
        [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Ansi)]
        public struct UNION
        {
            [FieldOffset(0)]
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)] 
            public String Command;
            [FieldOffset(0)]
	        public UInt16 Response;
        }
    }

    public class EloPubIf
    {
        private const int MAX_SUPPORTED_SCR = 256;

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetScreenInfo([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I4, SizeConst = MAX_SUPPORTED_SCR)] [Out] UInt32[] dwMonNo, ref Int32 iScrCnt);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetTouch(ref TOUCH_POINT tpxy, Int32 xlated, GETPOINTS_CODE getCode, ref UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloCancel();

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetMouseMode(ref Int16 pwMode, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetMouseMode(Int16 wMode, UInt32 nScrNo);
  
        [DllImport("EloPubIf.dll")]
        public static extern int EloGetTouchReportingState(ref Int32 pbFlag, UInt32 nScrNo);
  
        [DllImport("EloPubIf.dll")]
        public static extern int EloSetTouchReportingState(Int32 bFlag, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetDragDelay(ref DRAG_DELAY pDragDelay, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetDragDelay(ref DRAG_DELAY pDragDelay, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetBeep(ref BEEP psndVal, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetBeep(ref BEEP psndVal, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetTouchBoundary(ref TOUCH_BOUNDARY ptBndry, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetTouchBoundary(ref TOUCH_BOUNDARY ptBndry, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetCalibrationData(ref CALIBRATION pCalData, UInt32 nScrNum);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetCalibrationData(ref CALIBRATION pCalData, UInt32 nScrNum);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSwapButton(IntPtr hWnd, UInt32 dwCnt, UInt32 nScrNum);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetLeftHandedMouse(Int32 bFlag);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetDiagnosticsData(ref SCREEN_PROPERTIES pData, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetQuickTouch(ref QUICK_TOUCH pQTouch, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetQuickTouch(ref QUICK_TOUCH pQTouch, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetEdgeAccel(ref EDGE_ACCEL pAccel, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetEdgeAccel(ref EDGE_ACCEL pAccel, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetUntouchTimeout(ref UNTOUCH_TIMEOUT pUTimeout, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetUntouchTimeout(ref UNTOUCH_TIMEOUT pUTimeout, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetRightClickOnHold(ref RIGHT_BUTTON pRBHold, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetRightClickOnHold(ref RIGHT_BUTTON pRBHold, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetNVRamCalData(ref NVRAM_CAL_DATA pNVRamCalData, UInt32 nScrNo);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSendSmartsetCommand(ref SMARTSET_DATA pSmartsetData);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetSmartsetResponseStatus(ref SMARTSET_DATA pSmartsetData);
  
        [DllImport("EloPubIf.dll")]
        public static extern int EloGetSmartsetResponse(ref SMARTSET_DATA pSmartsetData);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetAprPreference(UInt32 nScreenIndex);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetAprPreference(UInt32 nScreenIndex, APR_PREFERENCES apr_pref);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetAprParameters(UInt32 nScreenIndex, ref UInt32 pnParameters, ref UInt32 pnParameterCount);

        [DllImport("EloPubIf.dll")]
        public static extern int EloSetAprParameters(UInt32 nScreenIndex, ref UInt32 pnParameters, UInt32 nParameterCount);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetClipRectangles(ref CLIP_RECT pClipRect);
  
        [DllImport("EloPubIf.dll")]
        public static extern int EloSetClipRectangles(ref CLIP_RECT pClipRect);

        [DllImport("EloPubIf.dll")]
        public static extern int EloGetSerialNumbers(UInt32 nScreenIndex, [In, Out] char[] pszUsbControllerSN, UInt32 nUsbControllerSNBufLen, [In, Out] char[] pszSensorSN, UInt32 nSensorSNBufLen);

    }

    public class Win32
    {    
        [DllImport("kernel32.dll")]
        public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault,
                                        [In, Out] char[] lpReturnedString, uint nSize, string lpFileName);

        [DllImport("kernel32.dll")]
        public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

        [DllImport("user32.dll")]
        public static extern int ShowCursor(bool bShow);

        [DllImport("USER32.DLL")]
        public static extern int FindWindow(string lpClassName, string lpWindowName);

        [DllImport("shlwapi.dll")]
        public static extern bool PathFileExists(string fname);
    }
}
