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

namespace RogerMfReaderExample.Mifare
{
    class EpsoParser
    {

        internal const UInt32 MIFARE_OK                 = 0x00;
        internal const UInt32 MIFARE_ERROR              = 0x01;
        internal const UInt32 MIFARE_WRONG_EPSO_FRAME   = 0x04;
        internal const UInt32 MIFARE_NEW_CARD_NOT_FOUND = 0x05;
        internal const UInt32 MIFARE_WRONG_KEY          = 0x06;
        internal const UInt32 MIFARE_WRONG_BLOCK        = 0x07;
        internal const UInt32 MIFARE_WRONG_PAGE         = 0x08;
        internal const UInt32 MIFARE_WRONG_SECTOR       = 0x09;

        internal const Byte MF_CLASSIC_KEY_TYPE_A       = 0x00;
        internal const Byte MF_CLASSIC_KEY_TYPE_B       = 0x01;
        internal const Byte VALUE_BLOCK_INCREMENT       = 0x00;
        internal const Byte VALUE_BLOCK_DECREMENT       = 0x01;
        internal const Byte VALUE_BLOCK_RESTORE         = 0x02;

        // ******************************************************************************
        // API functions
        // ******************************************************************************

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 mifareLibVer(StringBuilder Version, Int32 Length);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 readCardBufferHost(Byte ID, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, out Byte FrameLength);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 readCardBufferTerminal(Byte ID, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, Byte FrameLength, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 21)] Char[] CardCode);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 readCardIDHost(Byte ID, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, out Byte FrameLength);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 readCardIDTerminal(Byte ID, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, Byte FrameLength, [Out, MarshalAs(UnmanagedType.LPArray)] Byte[] CardCode, out Byte CardCodeLength);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 mfClassicReadHost(Byte ID, Byte Sector, Byte Block, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] Byte[] Key, Byte KeyType, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, out Byte FrameLength);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 mfClassicReadTerminal(Byte ID, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, Byte FrameLength, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] Byte[] Data);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 mfClassicWriteHost(Byte ID, Byte Sector, Byte Block, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] Byte[] Data, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] Byte[] Key, Byte KeyType, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, out Byte FrameLength);

        [DllImport("RogerMifare.dll", CallingConvention = CallingConvention.Cdecl)]
        static public extern UInt32 mfClassicWriteTerminal(Byte ID, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] Char[] Frame, Byte FrameLength);


        //Message convert
        public static String Return(UInt32 returnLibrary)
        {
            String infoStr = String.Empty;

            switch (returnLibrary)
            {
                case MIFARE_OK:
                    infoStr = "Frame OK";
                    break;

                case MIFARE_ERROR:
                    infoStr = "Frame ERROR";
                    break;

                case MIFARE_WRONG_EPSO_FRAME:
                    infoStr = "Wrong EPSO frame";
                    break;

                case MIFARE_NEW_CARD_NOT_FOUND:
                    infoStr = "New card not found";
                    break;

                case MIFARE_WRONG_KEY:                          
                    infoStr = "Wrong key type";
                    break;

                case MIFARE_WRONG_BLOCK:
                    infoStr = "Wrong block";
                    break;

                case MIFARE_WRONG_SECTOR:
                    infoStr = "Wrong sector";
                    break;

                default:

                    break;
            }

            if (returnLibrary != MIFARE_OK)
                InfoBuffer.error(infoStr);

            return infoStr;

        }

    }
}
