using System;
#if DEBUG
using System.Diagnostics;
#endif
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Pixiview.Illust;
using Pixiview.Resources;
using Pixiview.UI.Theme;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace Pixiview
{
    public class App : Application
    {
        // public properties
        public static AppTheme CurrentTheme { get; private set; }
        public static PlatformCulture CurrentCulture { get; private set; }

        public App()
        {
            Device.SetFlags(new string[0]);
        }

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

        private void InitPreferences()
        {
            Configs.SetCookie(Preferences.Get(Configs.CookieKey, null));
            Configs.SetUserId(Preferences.Get(Configs.UserIdKey, null));

            Configs.IsOnR18 = Preferences.Get(Configs.IsOnR18Key, false);
            Configs.SyncFavType = (SyncType)Preferences.Get(Configs.SyncFavTypeKey, 0);
            var isProxied = Preferences.Get(Configs.IsProxiedKey, false);
            if (isProxied)
            {
                var host = Preferences.Get(Configs.HostKey, string.Empty);
                int port = Preferences.Get(Configs.PortKey, 0);
                if (!string.IsNullOrEmpty(host) && port > 0)
                {
                    Configs.Proxy = new System.Net.WebProxy(host, port);
#if LOG
                    DebugPrint($"load proxy: {host}:{port}");
#endif
                }
                else
                {
                    Configs.Proxy = null;
                }
            }
            else
            {
                Configs.Proxy = null;
            }
        }

        private void InitLanguage()
        {
            var ci = EnvironmentService.GetCurrentCultureInfo();
            EnvironmentService.SetCultureInfo(ci);
            CurrentCulture = new PlatformCulture(ci.Name.ToLower());
        }

        private void SetTheme(AppTheme theme, bool force = false)
        {
            if (force || theme != CurrentTheme)
            {
                CurrentTheme = theme;
            }
            else
            {
                return;
            }
#if LOG
            DebugPrint($"application theme: {theme}");
#endif
            ThemeBase themeInstance;
            if (theme == AppTheme.Dark)
            {
                themeInstance = DarkTheme.Instance;
            }
            else
            {
                themeInstance = LightTheme.Instance;
            }
#if __IOS__
            var style = (StatusBarStyles)themeInstance[ThemeBase.StatusBarStyle];
            EnvironmentService.SetStatusBarStyle(style);
#elif __ANDROID__
            var color = (Color)themeInstance[ThemeBase.NavColor];
            EnvironmentService.SetStatusBarColor(color);
#endif
            Resources = themeInstance;
        }

        protected override void OnStart()
        {
            InitLanguage();
            MainPage = new AppShell();

            InitResources();
            InitPreferences();
        }

        protected override void OnSleep()
        {
            base.OnSleep();
        }

        protected override void OnResume()
        {
            var theme = AppInfo.RequestedTheme;
            SetTheme(theme);
        }
#if DEBUG
        public static void DebugPrint(string message)
        {
            Debug.WriteLine("[{0:HH:mm:ss.ffff}] - {1}", DateTime.Now, message);
        }
        public static void DebugError(string category, string message)
        {
            Debug.Fail(string.Format("[{0:HH:mm:ss.ffff}] - {1} - {2}", DateTime.Now, category, message));
        }
#else
        public static void DebugPrint(string message)
        {
            Console.WriteLine("[Debug.Print] - {0}", message);
        }
        public static void DebugError(string category, string message)
        {
            Console.Error.WriteLine(string.Format("[Debug.Error] - {0} - {1}", category, message));
        }
#endif
        public static bool OpenUrl(Uri uri)
        {
            var current = Current.MainPage;
            if (current != null && uri != null)
            {
                var url = uri.AbsolutePath;
                if ("pixiview".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
                {
                    var m = Regex.Match(url, "/artworks/([0-9]+)", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        var illust = new IllustItem { Id = m.Groups[1].Value };
                        var page = new ViewIllustPage(illust);
                        MainThread.BeginInvokeOnMainThread(() => current.Navigation.PushAsync(page));
                    }
                    else
                    {
                        MainThread.BeginInvokeOnMainThread(() => current.DisplayAlert(
                            url,
                            ResourceHelper.InvalidUrl,
                            ResourceHelper.Ok));
                    }
                }
                else
                {
                    url = System.Net.WebUtility.UrlDecode(url);
                    if (File.Exists(url))
                    {
                        IllustFavorite favObj;
                        try
                        {
                            favObj = Stores.LoadFavoritesIllusts(url);
                        }
                        catch (Exception ex)
                        {
                            DebugError("open.file", $"failed to parse file, name: {url}, error: {ex.Message}");
                            return true;
                        }
                        var path = Stores.FavoritesPath;
                        if (url == path)
                        {
                            return false;
                        }
                        if (File.Exists(path))
                        {
                            MainThread.BeginInvokeOnMainThread(async () =>
                            {
                                var opReplace = ResourceHelper.FavoritesReplace;
                                var opCombine = ResourceHelper.FavoritesCombine;
                                var result = await current.DisplayActionSheet(
                                    ResourceHelper.FavoritesOperation,
                                    ResourceHelper.Cancel,
                                    opCombine,
                                    opReplace);
                                if (result == opReplace)
                                {
                                    // replace favorite file
                                    File.Copy(url, path, true);
                                }
                                else if (result == opCombine)
                                {
                                    // combine favorite file
                                    var favNow = Stores.GetFavoriteObject();
                                    var list = favNow.Illusts;
                                    var distinct = favObj.Illusts.Where(f => !list.Any(i => i.Id == f.Id)).ToList();
                                    list.InsertRange(0, distinct);

                                    //favNow.Illusts = list;
                                    Stores.SaveFavoritesIllusts();
                                }

                                if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites))
                                {
                                    var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem;
                                    if (sc.PresentedPage is FavoritesPage fav)
                                    {
                                        fav.Reload(true);
                                    }
                                }
                            });
                        }
                        else
                        {
                            File.Copy(url, path);
                            if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites))
                            {
                                var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem;
                                if (sc.PresentedPage is FavoritesPage fav)
                                {
                                    fav.Reload(true);
                                }
                            }
                        }
                    }
                }
            }
            return true;
        }
    }
}
