using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;

namespace rglib.libtest {
    public partial class ProfilesEditDialog : Form {
        class ProfileTypeProxy : BindingProxy<ProfileType> {
            public ProfileTypeProxy(ProfileType wrappedObject) : base(wrappedObject) {
            }

            public override string ToString() {
                switch (Object) {
                    case ProfileType.APPLE_GOOGLE_PAY:
                        return "Apple/Goole Pay";
                    case ProfileType.MOBILE_ACCESS:
                        return "Мобильное приложение";
                    case ProfileType.MIFARE:
                        return "Mifare";
                }

                return "Неизвестно";
            }

            public override bool Equals(BindingProxy<ProfileType> other)
            {
                return other is ProfileTypeProxy && Object == other.Object;
            }

        }

        class MifareAuthTypeProxy : BindingProxy<MifareAuthType> {
            public MifareAuthTypeProxy(MifareAuthType wrappedObject) : base(wrappedObject) {
            }

            public override string ToString() {
                switch (Object) {
                    case MifareAuthType.SL1_CLASSIC:
                        return "SL1/Classic";
                    case MifareAuthType.SL3_PLUS:
                        return "SL3";
                }
                return "Неизвестно";
            }

            public override bool Equals(BindingProxy<MifareAuthType> other)
            {
                return other is MifareAuthTypeProxy && Object == other.Object;
            }
        }

        private readonly MifareProfile _profileData;
        private readonly bool _allowNfc;
        private readonly BindingList<ProfileTypeProxy> _profileTypes;
        private readonly BindingList<MifareAuthTypeProxy> _mifareAuthTypes;

        public ProfilesEditDialog() : this(new MifareProfile()) {

        }

        public ProfilesEditDialog(MifareProfile profileData, bool allowNfc = false)
        {
            InitializeComponent();
            _profileData = profileData;
            _allowNfc = allowNfc;

            _profileTypes = new BindingList<ProfileTypeProxy>();
            _mifareAuthTypes = new BindingList<MifareAuthTypeProxy>();
            profileTypeBox.BindingContext = new BindingContext();
            profileTypeBox.DataSource = _profileTypes;
            mifareAuthTypeBox.BindingContext = new BindingContext();
            mifareAuthTypeBox.DataSource = _mifareAuthTypes;
        }

        public void PrepareProfileAuthTypes() {
            _profileTypes.Clear();
            _profileTypes.Add(new ProfileTypeProxy(ProfileType.MIFARE));
            if (_allowNfc) {
                _profileTypes.Add(new ProfileTypeProxy(ProfileType.APPLE_GOOGLE_PAY));
                _profileTypes.Add(new ProfileTypeProxy(ProfileType.MOBILE_ACCESS));
            }
            profileTypeBox.Refresh();

            _mifareAuthTypes.Clear();
            _mifareAuthTypes.Add(new MifareAuthTypeProxy(MifareAuthType.SL1_CLASSIC));
            _mifareAuthTypes.Add(new MifareAuthTypeProxy(MifareAuthType.SL3_PLUS));
            mifareAuthTypeBox.Refresh();
        }

        private void PreloadData() {
            foreach (int i in Enumerable.Range(0, _profileTypes.Count)) {
               if (_profileTypes[i].Object == _profileData.ProfileType) {
                   profileTypeBox.SelectedIndex = i;
                   break;
               }   
            }

            foreach (int i in Enumerable.Range(0, _mifareAuthTypes.Count)) {
                if (_mifareAuthTypes[i].Object == _profileData.MifareAuthType) {
                    mifareAuthTypeBox.SelectedIndex = i;
                    break;
                }   
            }
            
            profileNameBox.Text = string.IsNullOrEmpty(_profileData.Name) ? "Новый профиль" : _profileData.Name;
            profileBlockBox.Value = _profileData.BlockNumber;

            cryptoOneType.SelectedIndex = _profileData.UseClassicKeyB ? 1 : 0;
            aesKeyType.SelectedIndex = _profileData.UsePlusKeyB ? 1 : 0;
            genKeyCheckBox.Checked = _profileData.UseGeneratedKey;
            presentKeyCheckBox.Checked = _profileData.UsePresentKey;
            emitKeyCheckBox.Checked = _profileData.UseEmitedKey;

            classicKeyHexBox.ByteProvider = new FixedByteProvider(_profileData.ClassicKey);
            plusKeyHexBox.ByteProvider = new FixedByteProvider(_profileData.PlusKey);
        }

        private void SaveButtonClick(object sender, EventArgs e) {
            SaveOnTypeRelative();
            DialogResult = DialogResult.OK;
            Close();
        }

        private void CancelButtonClick(object sender, EventArgs e) {
        }

        private void OnLoad(object sender, EventArgs e) {
            PrepareProfileAuthTypes();
            PreloadData();
        }

        private void SaveOnTypeRelative() {
            if (!string.IsNullOrEmpty(profileNameBox.Text) && profileNameBox.Text != _profileData.Name)
                _profileData.Name = profileNameBox.Text;

            if (profileTypeBox.SelectedItem is ProfileTypeProxy selectedProfileType)
            {
                _profileData.ProfileType = selectedProfileType.Object;

                if (selectedProfileType.Object == ProfileType.MIFARE)
                {
                    _profileData.MifareAuthType = (mifareAuthTypeBox.SelectedItem as MifareAuthTypeProxy)?.Object ?? MifareAuthType.SL1_CLASSIC;
                    _profileData.BlockNumber = Convert.ToByte(profileBlockBox.Value);
                    _profileData.UseClassicKeyB = cryptoOneType.SelectedIndex == 1;
                    _profileData.UsePlusKeyB = aesKeyType.SelectedIndex == 1;

                    if (classicKeyHexBox.ByteProvider.HasChanges())
                    {
                        classicKeyHexBox.ByteProvider.ApplyChanges();
                        Buffer.BlockCopy(((FixedByteProvider) classicKeyHexBox.ByteProvider).Bytes.ToArray(), 0,
                            _profileData.ClassicKey, 0, _profileData.ClassicKey.Length);
                    }

                    if (plusKeyHexBox.ByteProvider.HasChanges())
                    {
                        plusKeyHexBox.ByteProvider.ApplyChanges();
                        Buffer.BlockCopy(((FixedByteProvider) plusKeyHexBox.ByteProvider).Bytes.ToArray(), 0,
                            _profileData.PlusKey, 0, _profileData.PlusKey.Length);
                    }
                }
                else
                {
                    _profileData.UseGeneratedKey = genKeyCheckBox.Checked;
                    _profileData.UsePresentKey = presentKeyCheckBox.Checked;
                    _profileData.UseEmitedKey = emitKeyCheckBox.Checked;
                }
            }
        }

        private void ProfileTypeValueChanged(object sender, EventArgs e) {
            if (profileTypeBox.SelectedItem is ProfileTypeProxy selected) {
                if (selected.Object == ProfileType.MIFARE) {
                    mifareGroup.Enabled = true;
                    payGroup.Enabled = false;
                }
                else {
                    mifareGroup.Enabled = false;
                    payGroup.Enabled = true;
                }
            }
        }
    }
}
