using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Rglib.Interop;

namespace rglib.libtest
{
    public partial class IsoExchangeForm : Form
    {
        private Reader _reader;

        public IsoExchangeForm() {
            InitializeComponent();
            sakBytesBox.ByteProvider = new FixedByteProvider(new byte[2] {0, 0});
            atqaBytesBox.ByteProvider = new FixedByteProvider(new byte[2] {0, 0});
            uidBytesBox.ByteProvider = new FixedByteProvider(new byte[10] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
            atsBytesBox.ByteProvider = new FixedByteProvider(new byte[12] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

            blockByteBox.ByteProvider = new FixedByteProvider(new byte[2] {0, 0});
            keyByteBox.ByteProvider = new FixedByteProvider(new byte[16] {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255});

            blockClByteBox.ByteProvider = new FixedByteProvider(new byte[1] { 0 });
            keyClByteBox.ByteProvider = new FixedByteProvider(new byte[6] { 255, 255, 255, 255, 255, 255});

            readBlockByteBox.ByteProvider = new FixedByteProvider(new byte[1] { 0 });
            readBlockDataByteBox.ByteProvider = new FixedByteProvider(new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

            writeBlockByteBox.ByteProvider = new FixedByteProvider(new byte[1] { 0 });
            writeBlockDataByteBox.ByteProvider = new FixedByteProvider(new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
        }

        public IsoExchangeForm(Reader reader) : this() {
            _reader = reader;
        }

        private void IsoExchangeForm_Load(object sender, EventArgs e)
        {

        }

        private void resetFieldButton_Click(object sender, EventArgs e) {
            RG_ENDPOINT portEndpoin = _reader.Endpoint;
            try {
                var errorCode = Methods.RG_ResetField(ref portEndpoin, _reader.Address);
                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении Reset Field. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void RasButtonClick(object sender, EventArgs e) {
            ushort sak = 0;
            ushort atqa = 0;
            byte[] uid = new byte[10];
            RG_ENDPOINT portEndpoin = _reader.Endpoint;
            try {
                uint errorCode = Methods.RG_Iso_Ras(ref portEndpoin, _reader.Address, ref sak, ref atqa, uid, 10);
                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении RG_Iso_Ras. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }

                sakBytesBox.ByteProvider.WriteByte(0, (byte) (sak));
                sakBytesBox.ByteProvider.WriteByte(1, (byte) ((sak & 0xFF00) >> 8));
                sakBytesBox.Refresh();

                atqaBytesBox.ByteProvider.WriteByte(0, (byte)(atqa));
                atqaBytesBox.ByteProvider.WriteByte(1, (byte)((atqa & 0xFF00) >> 8));
                atqaBytesBox.Refresh();

                
                uidBytesBox.ByteProvider = new FixedByteProvider(uid);
                uidBytesBox.Refresh();
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void RatsButtonClick(object sender, EventArgs e)
        {
            byte[] uid = new byte[10];
            byte[] ats = new byte[16];
            int atsSize = 0;
            RG_ENDPOINT portEndpoin = _reader.Endpoint;
            try
            {
                var errorCode = Methods.RG_Iso_Rats(ref portEndpoin, _reader.Address, ats, 16, ref atsSize);
                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении RG_Iso_Rats. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }

                atsBytesBox.ByteProvider = new FixedByteProvider(ats.Take(atsSize).ToArray());
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void AuthButtonClick(object sender, EventArgs e) {
            byte[] key = ((FixedByteProvider) keyByteBox.ByteProvider).Bytes.ToArray();
            ushort block = BitConverter.ToUInt16(((FixedByteProvider) blockByteBox.ByteProvider).Bytes.ToArray(), 0);
            RG_ENDPOINT portEndpoin = _reader.Endpoint;
            try {
                var errorCode = Methods.RG_Iso_Auth(ref portEndpoin, _reader.Address, block, key, key.Length);
                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении RG_Iso_Auth. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void AuhClButtonClick(object sender, EventArgs e) {
            byte[] key = ((FixedByteProvider) keyClByteBox.ByteProvider).Bytes.ToArray();
            byte block = blockByteBox.ByteProvider.ReadByte(0);
            byte keyType = keyBClCheck.Checked ? (byte) 1 : (byte) 0;
            RG_ENDPOINT portEndpoin = _reader.Endpoint;
            try {
                var errorCode = Methods.RG_MF_AuthorizeClassic(ref portEndpoin, _reader.Address, block, keyType, key);
                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении RG_MF_AuthorizeClassic. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void MwReadButtonClick(object sender, EventArgs e) {
            byte block = readBlockByteBox.ByteProvider.ReadByte(0);
            byte flags = readPlCheck.Checked ? (byte) 2 : (byte) 0;
            byte[] data = new byte[16];
            RG_ENDPOINT portEndpoin = _reader.Endpoint;

            try {

                var errorCode =
                    Methods.RG_MF_ReadBlock(ref portEndpoin, _reader.Address, block, flags, data, data.Length);

                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении RG_MF_ReadBlock. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }

                readBlockDataByteBox.ByteProvider = new FixedByteProvider(data);
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void MfWriteButtonClick(object sender, EventArgs e) {
            byte block = writeBlockByteBox.ByteProvider.ReadByte(0);
            byte flags = writePlCheck.Checked ? (byte) 2 : (byte) 0;
            byte[] data = ((FixedByteProvider) writeBlockDataByteBox.ByteProvider).Bytes.ToArray();
            RG_ENDPOINT portEndpoin = _reader.Endpoint;

            try {
                var errorCode =
                    Methods.RG_MF_WriteBlock(ref portEndpoin, _reader.Address, block, flags, data, data.Length);

                if (errorCode != 0) {
                    throw new InvalidOperationException(
                        $"Ошибка при выполнении RG_MF_WriteBlock. {errorCode} {ApiErrorHelper.GetErrorDescription(errorCode)}");
                }
            }
            catch (Exception ex) {
                MessageBox.Show(this, ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
