using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Billing.Languages;
using Billing.Models;
using Billing.Store;
using Billing.Themes;
using Billing.UI;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace Billing
{
    public class App : Application
    {
        internal const string NewBillAction = "/newbill";

        public static AppTheme CurrentTheme { get; private set; }
        public static PlatformCulture CurrentCulture { get; private set; }
        public static List<Bill> Bills => bills ??= new List<Bill>();
        public static List<Account> Accounts => accounts ??= new List<Account>();
        public static List<Category> Categories => categories ??= new List<Category>();
        public static bool SaveLocation => saveLocation;
        public static string MainRoute => mainRoute;

        private static List<Bill> bills;
        private static List<Account> accounts;
        private static List<Category> categories;
        private static bool saveLocation;
        private static string mainRoute;

        private string initialUrl;

        public App(string url = null)
        {
            if (url == NewBillAction)
            {
#if __ANDROID__
                mainRoute = "//Bills/Details";
#endif
            }
            else
            {
                mainRoute = "//Bills";
                initialUrl = url;
            }
            CurrentCulture = new PlatformCulture();
            saveLocation = Preferences.Get(Definition.SaveLocationKey, false);
            InitResources();

            MainPage = new MainShell();
        }

        protected override void OnStart()
        {
            Helper.Debug($"personal folder: {StoreHelper.PersonalFolder}");
            Helper.Debug($"cache folder: {StoreHelper.CacheFolder}");

            if (initialUrl != null)
            {
                var url = initialUrl;
                initialUrl = null;
                _ = OpenUrl(url);
            }
        }

        protected override void OnResume()
        {
            SetTheme(AppInfo.RequestedTheme);
        }

        private void InitResources()
        {
            var theme = AppInfo.RequestedTheme;
            SetTheme(theme, true);
        }

        private void SetTheme(AppTheme theme, bool force = false)
        {
            if (force || theme != CurrentTheme)
            {
                CurrentTheme = theme;
            }
            else
            {
                return;
            }
            Helper.Debug($"application theme: {theme}");

            BaseTheme instance;
            if (theme == AppTheme.Dark)
            {
                instance = Dark.Instance;
            }
            else
            {
                instance = Light.Instance;
            }
            // TODO: status bar
            Resources = instance;
        }

        public static void SetSaveLocation(bool flag)
        {
            saveLocation = flag;
        }

        public static async Task InitializeData()
        {
            var instance = await StoreHelper.Instance;
            await Task.WhenAll(
                Task.Run(async () => accounts = await instance.GetListAsync<Account>()),
                Task.Run(async () => categories = await instance.GetListAsync<Category>()),
                Task.Run(async () => bills = await instance.GetListAsync<Bill>()));
        }

#if __ANDROID__
        public static async Task<bool> OpenUrl(string url)
#elif __IOS__
        public static bool OpenUrl(string url)
#endif
        {
            if (string.IsNullOrEmpty(url))
            {
                return false;
            }
            if (File.Exists(url))
            {
#if __ANDROID__
                var status = await Helper.CheckAndRequestPermissionAsync<Permissions.StorageRead>();
                if (status != PermissionStatus.Granted)
                {
                    return false;
                }
#endif
                _ = Task.Run(async () =>
                {
                    var result = await StoreHelper.ReloadDatabase(url);
                    if (result)
                    {
                        await InitializeData();

                        var current = Shell.Current.CurrentPage;
                        if (current is BillingPage page)
                        {
                            MainThread.BeginInvokeOnMainThread(() => page.TriggerRefresh());
                        }
                    }
                });
            }
            return true;
        }
    }
}