using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using RogerMfReaderExample.RUD3;


namespace RogerMfReaderExample.Mifare
{
    class Reader
    {

        private Byte FrameLength = 0;                  //Length recive o send bufer    
        private Byte ID = 0;
        private static UInt32 returnLibrary;

        private UsbReader Usb = new UsbReader();
        public Classic CardMifareClassic = new Classic(); 

        public Reader()
        {
           
        }

        //Get list all mifare proxy reader
        public List<String[]> FindAll()
        {
            //only RUD3
            var rud2s = getDevices(rud3.RUD_2);
            var rud3s = getDevices(rud3.RUD_3);
            
            for (int i = 0; i < rud3s.Count; i++)
            {
                rud2s.Add(rud3s[i]);
            }

            //Add rud4
            var rud4s = getDevices(rud3.RUD_4);
            for (int i = 0; i < rud4s.Count; i++)
            {
                rud2s.Add(rud4s[i]);
            }

            if (rud2s.Count == 0)
            {
                MessageBox.Show("No RUD Devices available");
            }
            return rud2s;
        }

        //Rud3 lib version
        public string GetlibVersion()
        {
            StringBuilder libraryVer = new StringBuilder(64);
            String retString = String.Empty;
            UInt32 ParserReturn;

            try
            {
                ParserReturn = EpsoParser.mifareLibVer(libraryVer, libraryVer.MaxCapacity);

                if (ParserReturn == EpsoParser.MIFARE_OK)
                    retString = libraryVer.ToString() + Environment.NewLine;

                retString += Usb.getLibraryVersion();
            }
            catch (Exception e)
            {
                InfoBuffer.error(e.Message);
                
            }

            return retString;
               
        }

        //Connect
        public Boolean connect(String serialNumber)
        {
            //only RUD3
            return Usb.connect(serialNumber);
        }

        //Disconect
        public Boolean disconnect()
        {
            //only RUD3
            return Usb.disconnect();
        }


        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 = rud3.rud3GetDeviceCount(ref deviceCount, deviceTypeId);

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

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

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

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

                        }

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

            }
            finally
            {
                //message();

            }

            return allRuds;
        }

       

        //Mifare classic card read block  
        public Byte[] ReadCard()
        {
             
            Char[] Frame = new Char[64];
            Byte[] DataTab = new Byte[16];
            ConsolBox Info = new ConsolBox("read card ");

            try
            { 
                //creat frame to send - host
                Info.AddHostData("sector", CardMifareClassic.sector);
                Info.AddHostData("block", CardMifareClassic.block);
                Info.AddHostData("key", CardMifareClassic.key);
                Info.AddHostData("key Type", CardMifareClassic.GetKeyType());

                UInt32 ParserReturn;

                //Dll create frame
                ParserReturn = EpsoParser.mfClassicReadHost(ID, CardMifareClassic.sector, CardMifareClassic.block, CardMifareClassic.key, CardMifareClassic.KeyType, Frame, out FrameLength);

                Info.HostReturn = EpsoParser.Return(ParserReturn);

                if (ParserReturn == EpsoParser.MIFARE_OK)
                {
                   // Info.AddHostData("Frame", new String(Frame));

                    //Comunication
                    String reciveFrame;
                    reciveFrame = Communication(Frame);

                    if (reciveFrame.Equals(String.Empty) == false)
                    {
                        //Terminala
                        // Info.AddTreminalData("Frame", reciveFrame);

                        //Dll parser data
                        ParserReturn = EpsoParser.mfClassicReadTerminal(ID, reciveFrame.ToCharArray(), (Byte)reciveFrame.Length, DataTab);

                        Info.TerminalReturn = EpsoParser.Return(ParserReturn);

                        if (ParserReturn == EpsoParser.MIFARE_OK)
                            Info.AddTreminalData("DATA", DataTab);
                    }

                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }
           
            return DataTab;
        }

        //Mifare classic card Write block  
        public Boolean WriteCard( Byte[] dataTab)
        {
            Char[] Frame = new Char[64];
            ConsolBox Info = new ConsolBox("mifare classic - write card ");
            Boolean returnValue =  false;
            
            try
            {
                //creat frame to send - host
                Info.AddHostData("sector", CardMifareClassic.sector);
                Info.AddHostData("block", CardMifareClassic.block);
                Info.AddHostData("key", CardMifareClassic.key);
                Info.AddHostData("key Type", CardMifareClassic.GetKeyType());
                Info.AddHostData("DATA", dataTab);

                UInt32 ParserReturn;
                //Dll create frame
                ParserReturn = EpsoParser.mfClassicWriteHost(ID, CardMifareClassic.sector, CardMifareClassic.block, dataTab, CardMifareClassic.key, CardMifareClassic.KeyType, Frame, out FrameLength);

                Info.HostReturn = EpsoParser.Return(ParserReturn);


                if (ParserReturn == EpsoParser.MIFARE_OK)
                {
                    //Info.AddHostData("Frame", new String(Frame));

                    //Comunication
                    String reciveFrame;
                    reciveFrame = Communication(Frame);

                    if (reciveFrame.Equals(String.Empty) == false)
                    {
                        //Info.AddTreminalData("Frame", reciveFrame);

                        ParserReturn = EpsoParser.mfClassicWriteTerminal(ID, reciveFrame.ToCharArray(), (Byte)reciveFrame.Length);
                        Info.TerminalReturn = EpsoParser.Return(ParserReturn);

                        if (ParserReturn == EpsoParser.MIFARE_OK)
                        {
                            InfoBuffer.info("Write OK");
                            returnValue = true;
                        }
                        else
                            returnValue = false;
                    }
                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
                returnValue = false;
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }

            return returnValue;
              
        }

        //Mifare classic card Read card buffer
        public Char[] ReadCardBuffer()
        {
            Char[] Frame = new Char[64];
            Char[] cardBuffer = new Char[21];
            ConsolBox Info = new ConsolBox("read card buffer ");

            try
            {

                UInt32 ParserReturn;
                //Dll create frame
                ParserReturn = EpsoParser.readCardBufferHost(ID, Frame, out FrameLength);

                Info.HostReturn = EpsoParser.Return(ParserReturn);


                if (ParserReturn == EpsoParser.MIFARE_OK)
                {
                    //Info.AddHostData("Frame", new String(Frame));

                    //Comunication
                    String reciveFrame;
                    reciveFrame = Communication(Frame);

                    if (reciveFrame.Equals(String.Empty) == false)
                    {
                        //Info.AddTreminalData("Frame", reciveFrame);

                        ParserReturn = EpsoParser.readCardBufferTerminal(ID, reciveFrame.ToCharArray(), (Byte)reciveFrame.Length, cardBuffer);
                        Info.TerminalReturn = EpsoParser.Return(ParserReturn);

                        if (ParserReturn == EpsoParser.MIFARE_OK)
                        {
                            Info.AddTreminalData("Card CODE", new String(cardBuffer).TrimEnd('\0'));
                            
                        }
                        
                    }
                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
                Array.Clear(cardBuffer,0,cardBuffer.Length);
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }

            return cardBuffer;

        }

        //Mifare classic card Read serial number
        public Byte[] ReadCardId()
        {
            Char[] Frame = new Char[64];
            Byte[] cardId = new Byte[10];
            ConsolBox Info = new ConsolBox("mifare classic - read card ID ");

            try
            {

                UInt32 ParserReturn;
                //Dll create frame
                ParserReturn = EpsoParser.readCardIDHost(ID, Frame, out FrameLength);

                Info.HostReturn = EpsoParser.Return(ParserReturn);


                if (ParserReturn == EpsoParser.MIFARE_OK)
                {
                    //Info.AddHostData("Frame", new String(Frame));

                    //Comunication
                    String reciveFrame;
                    reciveFrame = Communication(Frame);

                    if (reciveFrame.Equals(String.Empty) == false)
                    {
                        //Info.AddTreminalData("Frame", reciveFrame);
                        FrameLength = 0;
                        ParserReturn = EpsoParser.readCardIDTerminal(ID, reciveFrame.ToCharArray(), (Byte)reciveFrame.Length, cardId, out FrameLength);
                        Info.TerminalReturn = EpsoParser.Return(ParserReturn);

                        if (ParserReturn == EpsoParser.MIFARE_OK)
                        {
                            Array.Resize(ref cardId, FrameLength);
                            Info.AddTreminalData("Card ID", cardId);

                        }

                    }
                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
                Array.Clear(cardId, 0, cardId.Length);
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }

            return cardId;

        }
        #region RUD3_v2

        //Read RUD signature
        public string ReadSignature()
        {
            Char[] Frame = new Char[64];
            ConsolBox Info = new ConsolBox("Read Signature ");

            try
            {
                string frame = RUD3_v2.Epso.readSignature(ID);
                string answer = string.Empty;
                //Comunication
                string reciveFrame;
                reciveFrame = Communication(frame.ToCharArray());

                if (reciveFrame.Equals(string.Empty) == false)
                {
                    answer = RUD3_v2.Epso.getSignature(reciveFrame);
                    Info.AddTreminalData("Read Signature", answer);

                    return answer;
                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }
            return string.Empty;
        }
    
        //Read card code
        public string ReadCardCode()
        {
            Char[] Frame = new Char[64];
            ConsolBox Info = new ConsolBox("Read card code ");

            try
            {
                string frame = RUD3_v2.Epso.readCardBuffer(ID, (byte)'A', (byte)'1');
                string answer = string.Empty;
                //Comunication
                string reciveFrame;
                reciveFrame = Communication(frame.ToCharArray());

                if (reciveFrame.Equals(string.Empty) == false)
                {
                    answer = RUD3_v2.Epso.getCardBuffer(reciveFrame, (byte)'A', (byte)'1');
                    Info.AddTreminalData("Read card code", answer);

                    return answer;
                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }
            return string.Empty;
        }

        //RUD3_v2 Write card code
        public bool WriteCardCode(char[] cardCode)
        {
            Char[] Frame = new Char[64];
            ConsolBox Info = new ConsolBox("write card code ");

            try
            {
                string frame = RUD3_v2.Epso.writeCardCode(ID, cardCode);
                string answer = string.Empty;
                //Comunication
                string reciveFrame;
                reciveFrame = Communication(frame.ToCharArray());

                if (reciveFrame.Equals(string.Empty) == false)
                {
                     answer = RUD3_v2.Epso.getAnswer(reciveFrame, (byte)'5', (byte)'1');
                     Info.AddTreminalData("Write card code", answer);

                     return true;
                }
            }
            catch (Exception f)
            {
                InfoBuffer.error(f.Message);
            }
            finally
            {
                //Show in textbox
                Info.Show();
            }
            return false;
        }
        #endregion

        //Comunication
        private String Communication( Char[] charBuff)
        {
            String reciveBuffer = String.Empty;
            String sendBuffer = new String(charBuff);

            //Send Data - only RUD3
            if (Usb.IsConnect)      //
            {
                if (Usb.write(sendBuffer))
                {
                    reciveBuffer = Usb.read();
                }
            }
            else
            {
                InfoBuffer.error("No device connected!");
            }

            return reciveBuffer;

        }
    }



    
}
