using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using System.Xml.Serialization;
using System.IO;

namespace R_HH_M3O_LEG42_USB_SDK.NET_DEMO
{
    public partial class Main : Form
    {
        private enum EERROR
        {
            ER_OK = 0x00,
            ER_INVALID_POINTER,
            ER_NOT_IMPLEMENTED,
            ER_NO_PROTOCOL,
            ER_OPEN,
            ER_CLOSE,
            ER_WRITE,
            ER_READ,
            ER_SET_SPEED,
            ER_SET_TIMEOUT,
            ER_INVALID_DATA,
            ER_SIZE,
            ER_DATA,
            ER_DATA_SIZE,
            ER_MORE_DATA,
            ER_WRONG_APP,
            ER_CMD,
            ER_STATE,
            ER_NO_TRANSPORT,
            ER_CRC,
            ER_EXEC_CMD,
            ER_RCV_DATA,
            ER_SAM_FOUND,
            ER_SAM63_FOUND,
            ER_SAM64_FOUND_DATADEL,
            ER_SAM64_FOUND_DATAMEM,
            ER_SAM64_FOUND_MEMFULL,
            ER_MT_NOTSUPPORTED,
            ER_NO_TAG,
            ER_FEATURE,
            ER_OTHER_ERROR,
            ER_UNKNOWN = -1,
        }

        private enum EREADER_FEATURE
        {
            ERD_LEDS = 0x00,
            ERD_BUZZER,
            ERD_READER_TYPE,
            ERD_HARDWARE_REV,
            ERD_POWER,
            ERD_BOOT_LOADER,
            ERD_FIRMWARE,
            ERD_CRYPT_MODE,
            ERD_CARD,
            ERD_SELECT_FILE,
        }

        private enum ECARDTYPE
        {
            ECARD_LEGIC = 0x00,
            ECARD_ISO15693,
            ECARD_ISO14443A,
            ECARD_ISO14443B,
            ECARD_INSIDESECURE,
            ECARD_SONYFELICA
        }

        private enum EFILETYPE
        {
            FILE_IGNORE_SEG = 0x00,
            FILE_MT = 0x20,
            FILE_DATA_SEG = 0x40,
            FILE_LEGIC_SEG = 0x50,
            FILE_MT_PLUS = 0xC0
        }

        [DllImport("R-HH-M3O-LEG42-USB-SDK.dll")]
        public static extern IntPtr OpenReader(UInt32 nPort);

        [DllImport("R-HH-M3O-LEG42-USB-SDK.dll")]
        public static extern UInt32 GetReaderCaps(IntPtr hReader, UInt32 nRdFeat, byte[] pData, ref UInt32 dwCount);

        [DllImport("R-HH-M3O-LEG42-USB-SDK.dll")]
        public static extern UInt32 SetReaderCaps(IntPtr hReader, UInt32 nRdFeat, byte[] pData, UInt32 dwCount);

        [DllImport("R-HH-M3O-LEG42-USB-SDK.dll")]
        public static extern UInt32 ReadData(IntPtr hReader, UInt32 nAddress, byte[] pData, ref UInt32 dwCount);

        [DllImport("R-HH-M3O-LEG42-USB-SDK.dll")]
        public static extern UInt32 WriteData(IntPtr hReader, UInt32 nAddress, byte[] pData, UInt32 dwCount);

        [DllImport("R-HH-M3O-LEG42-USB-SDK.dll")]
        public static extern void CloseReader(IntPtr hReader);

        private IntPtr m_hReader;
        private UInt32 m_nScan;

        public Main()
        {
            InitializeComponent();

            m_hReader = new IntPtr(0x00);
            m_nScan = 0x00;
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            IntPtr hReader = OpenReader(0x01);
            if(hReader != null)
            {
                byte[] bufData = new byte[200]; UInt32 nCount = 200;

                GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_READER_TYPE, bufData, ref nCount);

                System.Text.ASCIIEncoding clsEnc = new System.Text.ASCIIEncoding();
                textInfoReaderType.Text = clsEnc.GetString(bufData, 0x00, bufData.Length);

                nCount = 200;
                GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_HARDWARE_REV, bufData, ref nCount);
                textInfoHarwareRev.Text = clsEnc.GetString(bufData, 0x00, bufData.Length);

                nCount = 200;
                GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_POWER, bufData, ref nCount);
                textInfoPower.Text = clsEnc.GetString(bufData, 0x00, bufData.Length);

                nCount = 200;
                GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_BOOT_LOADER, bufData, ref nCount);
                textInfoBootLoader.Text = clsEnc.GetString(bufData, 0x00, bufData.Length);

                nCount = 200;
                GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_FIRMWARE, bufData, ref nCount);
                textInfoFirware.Text = clsEnc.GetString(bufData, 0x00, bufData.Length);

                nCount = 200;
                GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_CRYPT_MODE, bufData, ref nCount);
                textInfoCryptMode.Text = clsEnc.GetString(bufData, 0x00, bufData.Length);

                CloseReader(hReader);
            }
        }

        // private string GetByteToString();
        private void buttonScan_Click(object sender, EventArgs e)
        {
            listViewScan.Items.Clear();
            m_hReader = OpenReader(0x01);
            if (m_hReader != null)
            {
                m_nScan = 0x00;
                timerScan.Enabled = true;
                buttonScan.Enabled = false;
            }

            /*buttonScan.Enabled = false;
            listViewScan.Items.Clear();
            IntPtr hReader = OpenReader(0x01);
            if (hReader != null)
            {
                string[] arCardType = {"Legic", "Iso 15693", "Iso 14443A", "Iso 14443B", "Insidesecure", "Sony Felica"};
                for (UInt32 nCardType = (UInt32)ECARDTYPE.ECARD_LEGIC; nCardType <= (UInt32)ECARDTYPE.ECARD_SONYFELICA; nCardType++)
                {
                    byte[] bufData = new byte[200]; UInt32 nCount = 200, nNav = 0x00;

                    BitConverter.GetBytes(nCardType).CopyTo(bufData, 0x00);
                    GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_CARD, bufData, ref nCount);

                    UInt32[] nNrCards = new UInt32[0x01];
                    Buffer.BlockCopy(bufData, 0, nNrCards, 0, 0x01);

                    nNav += 0x04;
                    for (UInt32 nStep = 0; nStep < nNrCards[0x00]; nStep++)
                    {
                        ListViewItem clsLstItem = new ListViewItem(new string[] { arCardType[nCardType], 
                                                        BitConverter.ToString(bufData, (int)nNav + 0x01, (int)bufData[nNav])});
                        listViewScan.Items.Add(clsLstItem);

                        nNav += bufData[nNav];
                    }
                }
                CloseReader(hReader);
            }
            buttonScan.Enabled = true;*/
        }

        private void buttonReadGetCard_Click(object sender, EventArgs e)
        {
            buttonReadGetCard.Enabled = false;
            comboReadCard.Items.Clear();

            IntPtr hReader = OpenReader(0x01);
            if (hReader != null)
            {
                for (UInt32 nCardType = (UInt32)ECARDTYPE.ECARD_LEGIC; nCardType <= (UInt32)ECARDTYPE.ECARD_SONYFELICA; nCardType++)
                {
                    byte[] bufData = new byte[200]; UInt32 nCount = 200, nNav = 0x00;

                    BitConverter.GetBytes(nCardType).CopyTo(bufData, 0x00);
                    if (GetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_CARD, bufData, ref nCount) == (UInt32)EERROR.ER_OK)
                    {
                        UInt32 nNrCards = BitConverter.ToUInt32(bufData, 0x00);

                        nNav += 0x04;
                        for (UInt32 nStep = 0; nStep < nNrCards; nStep++)
                        {
                            comboReadCard.Items.Add(BitConverter.ToString(bufData, (int)nNav + 0x01, (int)bufData[nNav]));
                            nNav += (UInt32)(bufData[nNav] + 0x01);
                        }
                    }
                }
                CloseReader(hReader);
            }

            comboReadCard.SelectedIndex = 0x00;
            buttonReadGetCard.Enabled = true;
        }

        private void buttonReadRead_Click(object sender, EventArgs e)
        {
	        if(comboReadCard.SelectedIndex != -1)
	        {
		        IntPtr hReader = OpenReader(0x01);
		        if(hReader != null)
		        {
                    UInt32[] arSelCard = new UInt32[0x03];
                    arSelCard[0x00] = (UInt32)ECARDTYPE.ECARD_LEGIC;
                    arSelCard[0x01] = (UInt32)comboReadCard.SelectedIndex;
                    arSelCard[0x02] = 0x00; // speed  !!!

                    byte[] bufData = new byte[200]; UInt32 nCount = 10;
                    Buffer.BlockCopy(bufData, 0, arSelCard, 0, arSelCard.Length);
			        EERROR eRet = (EERROR)SetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_CARD, bufData, (UInt32)(arSelCard.Length * 0x04));
			        if(eRet == EERROR.ER_OK)
			        {
                        UInt32[] arSelFile = new UInt32[0x03];

				        arSelFile[0x00] = 0x00; // segment
                        arSelFile[0x01] = (UInt32)EFILETYPE.FILE_DATA_SEG; // type of segment
				        arSelFile[0x02] = 0x00; // no stamp for segment

                        Buffer.BlockCopy(bufData, 0, arSelCard, 0, arSelCard.Length);
                        if ((eRet = (EERROR)SetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_SELECT_FILE, bufData, 
                                                                        (UInt32)(arSelFile.Length * 0x04))) == EERROR.ER_OK)
				        {
                            if ((eRet = (EERROR)ReadData(hReader, 0x01, bufData, ref nCount)) == EERROR.ER_OK)
					        {
                                textReadData.Text = BitConverter.ToString(bufData, 0x00, (int)nCount);
					        }
				        }
			        }
			        CloseReader(hReader);
		        }
	        }
        }

        private void buttonReadWrite_Click(object sender, EventArgs e)
        {
            if (comboReadCard.SelectedIndex != -1)
            {
                IntPtr hReader = OpenReader(0x01);
                if (hReader != null)
                {
                    UInt32[] arSelCard = new UInt32[0x03];
                    arSelCard[0x00] = (UInt32)ECARDTYPE.ECARD_LEGIC;
                    arSelCard[0x01] = (UInt32)comboReadCard.SelectedIndex;
                    arSelCard[0x02] = 0x00; // speed  !!!

                    byte[] bufData = new byte[200]; UInt32 nCount = 10;
                    Buffer.BlockCopy(bufData, 0, arSelCard, 0, arSelCard.Length);
                    EERROR eRet = (EERROR)SetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_CARD, bufData, (UInt32)(arSelCard.Length * 0x04));
                    if (eRet == EERROR.ER_OK)
                    {
                        UInt32[] arSelFile = new UInt32[0x03];

                        arSelFile[0x00] = 0x00; // segment
                        arSelFile[0x01] = (UInt32)EFILETYPE.FILE_DATA_SEG; // type of segment
                        arSelFile[0x02] = 0x00; // no stamp for segment

                        Buffer.BlockCopy(bufData, 0, arSelCard, 0, arSelCard.Length);
                        if ((eRet = (EERROR)SetReaderCaps(hReader, (UInt32)EREADER_FEATURE.ERD_SELECT_FILE, bufData,
                                                                        (UInt32)(arSelFile.Length * 0x04))) == EERROR.ER_OK)
                        {
                            if ((eRet = (EERROR)WriteData(hReader, 0x01, bufData, nCount)) != EERROR.ER_OK)
                            {
                                MessageBox.Show("Error during writing");
                            }
                        }
                    }
                    CloseReader(hReader);
                }
            }
        }

        private void Main_Load(object sender, EventArgs e)
        {
            comboReadData.Items.Clear();
            for (UInt32 bCount = 0x00; bCount <= 0xFF; bCount++)
            {
                comboReadData.Items.Add(bCount.ToString("X2"));
            }
            comboReadData.SelectedIndex = 0x00;
        }

        private void checkBoxScanSaveCardUID_CheckStateChanged(object sender, EventArgs e)
        {
            buttonScanPath.Enabled = checkBoxScanSaveCardUID.Checked ? true : false;
        }

        private void buttonScanPath_Click(object sender, EventArgs e)
        {
            SaveFileDialog clsFileDialog = new SaveFileDialog();
            clsFileDialog.Filter = "Xml|*.xml";
            if (clsFileDialog.ShowDialog() == DialogResult.OK)
            {
                textBoxScanPath.Text = clsFileDialog.FileName;
            }
        }

        private bool CheckUID(string strUID)
        {
            bool bRet = false;
            for (int iCount = 0x00; iCount < listViewScan.Items.Count; iCount++)
            {
                if (listViewScan.Items[iCount].SubItems[0x01].Text == strUID)
                {
                    bRet = true;
                }
            }
            return bRet;
        }

        private void timerScan_Tick(object sender, EventArgs e)
        {
            if (m_hReader != null)
            {
                string[] arCardType = { "Legic", "Iso 15693", "Iso 14443A", "Iso 14443B", "Insidesecure", "Sony Felica" };
                for (UInt32 nCardType = (UInt32)ECARDTYPE.ECARD_LEGIC; nCardType <= (UInt32)ECARDTYPE.ECARD_SONYFELICA; nCardType++)
                {
                    byte[] bufData = new byte[200]; UInt32 nCount = 200, nNav = 0x00;

                    BitConverter.GetBytes(nCardType).CopyTo(bufData, 0x00);
                    GetReaderCaps(m_hReader, (UInt32)EREADER_FEATURE.ERD_CARD, bufData, ref nCount);

                    UInt32[] nNrCards = new UInt32[0x01];
                    Buffer.BlockCopy(bufData, 0, nNrCards, 0, 0x01);

                    string strUID = "";
                    nNav += 0x04;
                    for (UInt32 nStep = 0; nStep < nNrCards[0x00]; nStep++)
                    {
                        strUID = BitConverter.ToString(bufData, (int)nNav + 0x01, (int)bufData[nNav]);
                        if (CheckUID(strUID) == false)
                        {
                            ListViewItem clsLstItem = new ListViewItem(new string[] { arCardType[nCardType], strUID });
                            listViewScan.Items.Add(clsLstItem);
                        }

                        nNav += (UInt32)(bufData[nNav] + 0x01);
                    }
                }
            }

            if (m_nScan == 40)
            {
                CloseReader(m_hReader);
                m_hReader           = (IntPtr)0x00;
                timerScan.Enabled   = false;
                buttonScan.Enabled  = true;

                if (checkBoxScanSaveCardUID.Checked && (textBoxScanPath.Text.Length > 0x04))
                {
                    CardInfoList clsCardInfoList = new CardInfoList();
                    clsCardInfoList.CardInfoList1 = new CardInfoType[listViewScan.Items.Count];

                    for (int iCount = 0x00; iCount < listViewScan.Items.Count; iCount++)
                    {
                        CardInfoType clsInfoType    = new CardInfoType();
                        clsInfoType.CardType        = listViewScan.Items[iCount].SubItems[0x00].Text;
                        clsInfoType.ReaderName      = "OEM-LEGIC-M3O";
                        clsInfoType.Time            = DateTime.Now.ToString("dd/MM/yyyy hh:mm");
                        clsInfoType.CardUID         = listViewScan.Items[iCount].SubItems[0x01].Text;

                        clsCardInfoList.CardInfoList1[iCount] = clsInfoType;
                    }

                    XmlSerializer serializer = new XmlSerializer(typeof(CardInfoList));
                    using (StreamWriter writer = new StreamWriter(textBoxScanPath.Text))
                    {
                        serializer.Serialize(writer, clsCardInfoList);
                    }
                }
                MessageBox.Show("End scanning");
            }

            m_nScan++;

            buttonScan.Enabled = true;
        }
    }
}