using Android.App;
using Android.Content;
using Android.Nfc;
using Android.Nfc.Tech;
using AndroidX.Activity;
using Com.Lvcheng.Lock.Shared.Nfc.Example.Java;
using NFCLockAppV2;
using NFCLockDemoV2.Platforms.Android;

namespace NFCLockDemoV2;

public class NFCLockHelper
{
    private readonly MainActivity _activity;
    private readonly NFCCallbacks _callbacks;
    
    private readonly NfcAdapter _nfcAdapter;
    private readonly PendingIntent _pendingIntent;
    private string[][] _techLists = [[typeof(NfcA).FullName, typeof(NdefFormatable).FullName, typeof(MifareUltralight).FullName]];
    private IntentFilter[] _intentFilters = [new(NfcAdapter.ActionNdefDiscovered), new(NfcAdapter.ActionTechDiscovered), new(NfcAdapter.ActionTagDiscovered)];
    private volatile bool _processing = false;
    
    public NFCLockHelper(MainActivity activity, NFCCallbacks callbacks)
    {
        _activity = activity;
        _callbacks = callbacks;
        _nfcAdapter = NfcAdapter.GetDefaultAdapter(_activity);
        _pendingIntent = PendingIntent.GetActivity(_activity, 0, new Intent(_activity, typeof(MainActivity)).AddFlags(ActivityFlags.ReceiverReplacePending), PendingIntentFlags.Mutable);
    }

    public void OnResume()
    {
        if (_nfcAdapter != null)
        {
            _nfcAdapter.EnableForegroundDispatch(_activity, _pendingIntent, _intentFilters, _techLists);
        }
    }
    
    public void OnPause()
    {
        if (_nfcAdapter != null)
        {
            _nfcAdapter.DisableForegroundDispatch(_activity);
        }
    }
    
    public void OnNewIntent(Intent intent)
    {
        if (!_processing)
        {
            
            if (intent != null && (intent.Action == NfcAdapter.ActionNdefDiscovered ||
                                   intent.Action == NfcAdapter.ActionTechDiscovered ||
                                   intent.Action == NfcAdapter.ActionTagDiscovered))
            {
                Task.Run(async() =>
                {
                    try
                    {
                        _processing = true;
                        Tag? tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
                        if (tag != null)
                        {
                            NfcA? nfcA = NfcA.Get(tag);
                            if (nfcA != null)
                            {
                                nfcA.Connect();
                                nfcA.Timeout = 1000;
                                Process(nfcA);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        _callbacks.OnLost();
                        Console.WriteLine(e);
                    }
                    finally
                    {
                        await Task.Delay(2000);
                        _processing = false;
                        _callbacks.OnFinished();
                    }
                });
            }
        }
    }

    private void Process(NfcA nfcA)
    {
        DeviceManagerWrapper wrapper = new DeviceManagerWrapper(nfcA);

        try
        {
            Com.Lvcheng.Lock.Shared.Nfc.Result initRes = wrapper.Init();
            if (initRes.Equals(Com.Lvcheng.Lock.Shared.Nfc.Result.Ok))
            {
                long? id;
                bool? isNew;
                int? mRssi;

                while (true)
                {
                    Com.Lvcheng.Lock.Shared.Nfc.Result getInfoRes = wrapper.Info;
                    if (!getInfoRes.Equals(Com.Lvcheng.Lock.Shared.Nfc.Result.Ok))
                        return;

                    _ = wrapper.Rssi;
                    id = wrapper.MGetId().LongValue();
                    isNew = wrapper.MGetIsNew().BooleanValue();
                    mRssi = wrapper.MGetRssi().IntValue();

                    bool continueLoop = _callbacks.OnLoop(wrapper, id, isNew, mRssi);

                    if (!continueLoop)
                        break;
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
}