using System;
using System.IO;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Xamarin.Essentials;
using XF.Material.Forms.UI.Dialogs;

namespace InABox.Mobile
{
    
    public abstract class MobileDocumentSource
    {
        public abstract Task<MobileDocument> From();
    }
    
    public abstract class MobileDocumentSource<TOptions> : MobileDocumentSource 
        where TOptions : class, IMobileDocumentOptions, new()
    {

        public TOptions Options { get; set; }

        protected MobileDocumentSource(TOptions options)
        {
            Options = options;
        }
        
        protected abstract Task<bool> IsEnabled();
        
        protected async Task<bool> IsEnabled<TPermission>()
            where TPermission : Permissions.BasePermission, new()
        {
            var status = await Permissions.CheckStatusAsync<TPermission>();
            if (status != PermissionStatus.Granted && status != PermissionStatus.Restricted)
                status = await Permissions.RequestAsync<TPermission>();
            return status == PermissionStatus.Granted;
        }
        
        protected abstract Task<FileResult> Capture();
        
        public override async Task<MobileDocument> From()
        {
            var result = new MobileDocument();
            if (await IsEnabled())
            {
                try
                {
                    var file = await Capture();
                    if (file != null)
                    {
                        result.FileName = Path.GetFileName(file.FileName); //file.OriginalFilename ?? file.Path);
                        await using (var stream = await file.OpenReadAsync())
                        {
                            BinaryReader br = new BinaryReader(stream);
                            result.Data = br.ReadBytes((int)stream.Length);
                        }
                    }
                    ApplyOptions(result);
                }
                catch (FeatureNotSupportedException fnsEx)
                {
                    await MaterialDialog.Instance.AlertAsync("This operation is not Supported on this Device!");
                    MobileLogging.Log(fnsEx, "Capture(FNS)");
                }
                catch (PermissionException pEx)
                {
                    await MaterialDialog.Instance.AlertAsync("This operation is not Permitted on this Device!");
                    MobileLogging.Log(pEx, "Capture(PERM)");
                }
                catch (Exception ex)
                {
                    await MaterialDialog.Instance.AlertAsync("Oops! Something went wrong!  Please try again..");
                    MobileLogging.Log(ex, "Capture(ERR)");
                }
            }
            return result;
        }

        protected abstract void ApplyOptions(MobileDocument document);

    }
}