using Borepin.Base;
using Borepin.Service;
using FabAccessAPI.Schema;
using Prism.Commands;
using Prism.Navigation;
using Prism.Services;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using ZXing;
using ZXing.Mobile;

namespace Borepin.PageModel
{
    class ScanURNPageModel : ConnectionModelBase
    {
        #region Contructors
        public ScanURNPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService)
        {
            CancelCommand = new DelegateCommand(async () => await CancelCommandExecute().ConfigureAwait(true));
            ScannedCommand = new DelegateCommand(async () => await ScannedCommandExecuteAsync().ConfigureAwait(false));

            IsVisible = true;
            IsScanning = true;
        }
        #endregion

        #region Fields
        public MobileBarcodeScanningOptions ScanOptions
        {
            get
            {
                return new MobileBarcodeScanningOptions()
                {
                    PossibleFormats = new List<BarcodeFormat>()
                    {
                        BarcodeFormat.QR_CODE,
                        BarcodeFormat.EAN_13,
                    },
                    AutoRotate = true,
                    DelayBetweenContinuousScans = 300,
                };
            }
        }

        private Result _ScanResult;
        public Result ScanResult
        {
            get => _ScanResult;
            set => SetProperty(ref _ScanResult, value);
        }

        private bool _IsScanning;
        public bool IsScanning
        {
            get => _IsScanning;
            set => SetProperty(ref _IsScanning, value);
        }

        private bool _IsVisible;
        public bool IsVisible
        {
            get => _IsVisible;
            set => SetProperty(ref _IsVisible, value);
        }
        #endregion

        #region Commands
        private ICommand _ScannedCommand;

        public ICommand ScannedCommand
        {
            get => _ScannedCommand;
            set => SetProperty(ref _ScannedCommand, value);
        }

        public async Task ScannedCommandExecuteAsync()
        {
            IsScanning = false;

            // HACK
            if(string.Equals(ScanResult.Text, "4014472002512", System.StringComparison.Ordinal))
            {
                Device.BeginInvokeOnMainThread(async () =>
                {
                    await _PageDialogService.DisplayAlertAsync(Resources.Text.TextResource.YAY, Resources.Text.TextResource.Bionade, Resources.Text.TextResource.OK).ConfigureAwait(false);
                    IsScanning = true;
                });
                return;
            }
            // END HACK

            string id = await QRToID(ScanResult.Text).ConfigureAwait(false);

            if (id != null)
            {
                NavigationParameters parameters = new NavigationParameters
                {
                    { "instance", id },
                };

                Device.BeginInvokeOnMainThread(async () =>
                {
                    INavigationResult result = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/MachineListPage/MachinePage", parameters).ConfigureAwait(false);
                });
            }
            else
            {
                Device.BeginInvokeOnMainThread(async () =>
                {
                    await _PageDialogService.DisplayAlertAsync(Resources.Text.TextResource.ALERT, Resources.Text.TextResource.ALERT_QRInvalid, Resources.Text.TextResource.OK).ConfigureAwait(false);
                    IsScanning = true;
                });
                return;
            }

            IsScanning = true;
        }

        public async Task<string> QRToID(string value)
        {
            if (_API.IsConnected)
            {
                Optional<Machine> optional = await _API.Session.MachineSystem.Info.GetMachineURN(value).ConfigureAwait(false);

                if (optional.Just == null)
                {
                    return null;
                }

                return optional.Just.Id;
            }
            else
            {
                return null;
            }
        }

        private ICommand _CancelCommand;
        public ICommand CancelCommand
        {
            get => _CancelCommand;
            set => SetProperty(ref _CancelCommand, value);
        }
        public async Task CancelCommandExecute()
        {
            IsScanning = false;

            await _NavigationService.GoBackAsync().ConfigureAwait(false);
        }
        #endregion
    }
}
