using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RogerRud.RUD;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;

namespace RogerRud.RUD
{
    class UsbReader
    {
        private static UInt32 readTimeOut = 1000;   
        private static UInt32 writeTimeOut = 100;
        private static Boolean Connect;
        private static IntPtr Handle = new IntPtr();
        private static UInt32 returnLibrary;
        private rud ter = new rud();

        public UsbReader()
        {
            Connect = false;
            Handle = IntPtr.Zero;
            returnLibrary = rud.RUD3_OK;
        }

        
        /// <summary>
        /// Check if usb reader is in connected state
        /// </summary>
        public Boolean IsConnect
        {
            get
            {
                if ((Connect = true) && (Handle != IntPtr.Zero))
                    return true;
                else
                    return false;
            }
        }

        
        /// <summary>
        /// Library version
        /// </summary>
        /// <returns></returns>
        static public String getLibraryVersion()
        {
            StringBuilder libraryVer = new StringBuilder(64);

            try
            {
                returnLibrary = rud.rud3LibVer(libraryVer, libraryVer.MaxCapacity);

                if (returnLibrary != rud.RUD3_OK)
                    return String.Empty;
                else
                    return libraryVer.ToString();

            }
            catch (Exception e)
            {
                message(e.Message);
                return String.Empty;
            }
            finally
            {
                message();
            }
        }

        /// <summary>
        /// Get list of usb readers 
        /// </summary>
        /// <param name="deviceTypeId"> Device identification - RUD_3, RUD_2 or ALL_DEVICES </param>
        /// <returns>List of connected devices</returns>
        public List<String[]> getDevices(UInt16 deviceTypeId)
        {
            UInt32 deviceCount = 0;
            List<String[]> allRuds = new List<String[]>();
            StringBuilder serialNr = new StringBuilder(126);        //Serial number
            StringBuilder description = new StringBuilder(126);     //Description
            StringBuilder port = new StringBuilder(126);            //Port name

            try
            {
                //For all RUD devices use deviceTypeId == ALL_DEVICES
                returnLibrary = rud.rud3GetDeviceCount(ref deviceCount, deviceTypeId);      

                if (returnLibrary == rud.RUD3_OK)
                {
                    for (UInt32 i = 0; i < deviceCount; i++)
                    {
                        serialNr.Clear();
                        description.Clear();
                        port.Clear();

                        returnLibrary = rud.rud3GetSerialNumber(i, deviceTypeId, serialNr);                 //Get serial number

                        if(returnLibrary == rud.RUD3_OK)
                        {
                            returnLibrary = rud.rud3GetDescriptionBySerialNumber(serialNr, description);   //Get decription

                            if (returnLibrary == rud.RUD3_OK)
                            {
                                returnLibrary = rud.rud3GetPort(serialNr, port);                           //Get port
                            }

                        }

                        if (returnLibrary == rud.RUD3_OK)
                        {   
                            //Add to list
                            String[] data = new String[] { serialNr.ToString(), description.ToString(), port.ToString() };
                            allRuds.Add(data);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                message(e.Message);
                
            }
            finally 
            {
               message();
                
            }

            return allRuds;
        }

        /// <summary>
        /// Connect to usb reader
        /// </summary>
        /// <param name="serialNumber">Serial number</param>
        /// <returns>true - connected, false - not connected</returns>
        public Boolean connect(String serialNumber)
        {
            StringBuilder serialNr = new StringBuilder(serialNumber);
            
            try
            {
                returnLibrary = rud.rud3Open(ref Handle, serialNr);
               
                if (returnLibrary == rud.RUD3_OK)
                    Connect = true;
                else
                    Connect = false;
                
            }
            catch (Exception e)
            {
                Connect = false; 
                message(e.Message);
                
            }
            finally
            {
                message();

            }

            return Connect;
        }

        
        /// <summary>
        /// Disconnect usb reader
        /// </summary>
        /// <returns>true - not connected, false - connected</returns>
        public Boolean disconnect()
        {
            try
            {
                returnLibrary = rud.rud3Close(ref Handle);

                if (returnLibrary == rud.RUD3_OK)
                {
                    Connect = false;
                    Handle = IntPtr.Zero;
                }
             

            }
            catch (Exception e)
            {
                Connect = false;
                message(e.Message);

            }
            finally
            { 
                message();
               
            }

            return !Connect;
        }

        /// <summary>
        /// Read from connected usb reader
        /// </summary>
        /// <returns> readed string or empty string</returns>
        public String read(  )
        {
            StringBuilder readBuf = new StringBuilder(64);  //64 max send/recvie frame size
            UInt32 readedData = 0;
           
            try
            {
                returnLibrary = rud.rud3Read(ref Handle, readBuf, 64, out readedData, readTimeOut);

                if (returnLibrary == rud.RUD3_OK)
                {
                    readBuf.Length = (Int32)readedData;
                }
                   
            }
            catch (Exception e)
            {
                Connect = false;
                message(e.Message);

            }
            finally
            {
                message();
               
            }

            return readBuf.ToString();
        }

       
        /// <summary>
        /// Write to connected usb reader
        /// </summary>
        /// <param name="data"> data to write</param>
        /// <returns> true -  write complete, false-  write error</returns>
        public Boolean write(String data)
        {
            Boolean readReturn = false;
            UInt32 writeData;

            try
            {
                returnLibrary = rud.rud3Write(ref Handle, data, (UInt32)data.Length, out writeData, writeTimeOut);

                if (returnLibrary == rud.RUD3_OK)
                    readReturn = true;
                else
                    readReturn = false;
            }
            catch (Exception e)
            {
                Connect = false;
                message(e.Message);

            }
            finally
            {
                message();

            }

            return readReturn;
        }

        
        /// <summary>
        /// Message generated from value returned  by  library functions 
        /// </summary>
        static private void message()
        {
            switch (returnLibrary)
            {
                case rud.RUD3_ERROR:
                    
                    MessageBox.Show("Roger RUD library - error", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_DEVICE_NOT_FOUND:
                    
                    MessageBox.Show("Roger RUD library  - devices not found", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_DEVICE_CANNOT_OPEN:
                    
                    MessageBox.Show("Roger RUD library - cannot open communication channel", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_INVALID_BUFFER_SIZE:
                    
                    MessageBox.Show("Roger RUD library - invalid buffer size", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_EPSO_ERROR:                          //Don't exist
                   
                    MessageBox.Show("Roger RUD library - epso error", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_USB_HID_ERROR:
                    
                    MessageBox.Show("Roger RUD library - usb hid error", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_TIMEOUT:
                    
                    MessageBox.Show("Roger RUD library - timeout", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_CARD_NOT_FOUND:
                    
                    MessageBox.Show("Roger RUD library - new card not found", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_DEVICE_CANNOT_CLOSE:
                    
                    MessageBox.Show("Roger RUD library - cannot close communication channel", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_WRITE_ERROR:
                  
                    MessageBox.Show("Roger RUD library - write error", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                case rud.RUD3_READ_ERROR:
                    
                    MessageBox.Show("Roger RUD library - read error", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;

                default:
                    break;
            }
            
            //Clear
            returnLibrary = rud.RUD3_OK;

        }

        /// <summary>
        /// Error message
        /// </summary>
        /// <param name="msg"> message string</param>
        static private void message(String msg)
        {
            MessageBox.Show(msg, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //Clear
            returnLibrary = rud.RUD3_OK;
        }
    }
}
