using System;
using System.Threading.Tasks;
using Pixiview.Login;
using Pixiview.Resources;
using Pixiview.UI;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace Pixiview
{
    public partial class AppShell : Shell
    {
        public static new AppShell Current => Shell.Current as AppShell;

        public static Thickness NavigationBarOffset { get; private set; }
        public static Thickness HalfNavigationBarOffset { get; private set; }
        public static Thickness TotalBarOffset { get; private set; }

        public static readonly BindableProperty UserProfileImageProperty = BindableProperty.Create(
            nameof(UserProfileImage), typeof(ImageSource), typeof(AppShell), StyleDefinition.ProfileNone);
        public static readonly BindableProperty UserProfileNameProperty = BindableProperty.Create(
            nameof(UserProfileName), typeof(string), typeof(AppShell), ResourceHelper.Guest);
        public static readonly BindableProperty UserProfileIdProperty = BindableProperty.Create(
            nameof(UserProfileId), typeof(string), typeof(AppShell));
        public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
            nameof(IsLoading), typeof(bool), typeof(AppShell));

        public ImageSource UserProfileImage
        {
            get => (ImageSource)GetValue(UserProfileImageProperty);
            set => SetValue(UserProfileImageProperty, value);
        }
        public string UserProfileName
        {
            get => (string)GetValue(UserProfileNameProperty);
            set => SetValue(UserProfileNameProperty, value);
        }
        public string UserProfileId
        {
            get => (string)GetValue(UserProfileIdProperty);
            set => SetValue(UserProfileIdProperty, value);
        }
        public bool IsLoading
        {
            get => (bool)GetValue(IsLoadingProperty);
            set => SetValue(IsLoadingProperty, value);
        }

        public event EventHandler<BarHeightEventArgs> NavigationBarHeightChanged;
        public event EventHandler<BarHeightEventArgs> StatusBarHeightChanged;

        private bool firstLoading = true;

        public AppShell()
        {
            BindingContext = this;
            InitializeComponent();

#if LOG
            App.DebugPrint($"folder: {Stores.PersonalFolder}");
            App.DebugPrint($"cache: {Stores.CacheFolder}");
#endif
        }

        protected override void OnNavigated(ShellNavigatedEventArgs args)
        {
            if (firstLoading)
            {
                firstLoading = false;
                // login info
                Task.Run(() => DoLoginInformation(true));
            }
        }

        public void SetNavigationBarHeight(double height)
        {
            NavigationBarOffset = new Thickness(0, height, 0, 0);
            HalfNavigationBarOffset = new Thickness(0, height / 2, 0, 0);

            NavigationBarHeightChanged?.Invoke(this, new BarHeightEventArgs
            {
                NavigationBarHeight = height
            });
        }

        public void SetStatusBarHeight(double height)
        {
            TotalBarOffset = new Thickness(0, NavigationBarOffset.Top + height, 0, 0);

            StatusBarHeightChanged?.Invoke(this, new BarHeightEventArgs
            {
                StatusBarHeight = height
            });
        }

        private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {
            if (UserProfileId != null)
            {
                if (IsLoading)
                {
                    return;
                }
                IsLoading = true;
                Task.Run(() =>
                {
                    DoLoginInformation(true);
                    IsLoading = false;
                });
            }
            else
            {
                PushToLogin(() =>
                {
                    Task.Run(() => DoLoginInformation(true));
                });
            }
        }

        private bool isLoginOpened;

        public void PushToLogin(Action after)
        {
            if (isLoginOpened)
            {
                return;
            }
            isLoginOpened = true;
            var loginPage = new LoginPage(()=>
            {
                isLoginOpened = false;
                after?.Invoke();
            });
            loginPage.Disappearing += (sender, e) =>
            {
                isLoginOpened = false;
            };
            MainThread.BeginInvokeOnMainThread(async () =>
            {
                await Navigation.PushModalAsync(loginPage);
            });
        }

        public void DoLoginInformation(bool force = false)
        {
            string name = null;
            string userId = null;
            string img = null;
            if (!force)
            {
                name = Preferences.Get(Configs.ProfileNameKey, null);
                userId = Preferences.Get(Configs.ProfileIdKey, null);
                img = Preferences.Get(Configs.ProfileImageKey, null);
            }
            if (name == null || userId == null)
            {
                var global = Stores.LoadGlobalData(force);
                if (global == null || global.userData == null)
                {
                    App.DebugError("login.info", "user data is null");
                    return;
                }
                name = global.userData.name;
                userId = global.userData.pixivId;
                img = global.userData.profileImgBig;
                Preferences.Set(Configs.ProfileNameKey, name);
                Preferences.Set(Configs.ProfileIdKey, userId);
                Preferences.Set(Configs.ProfileImageKey, img);
            }
            UserProfileName = name ?? ResourceHelper.Guest;
            UserProfileId = string.IsNullOrEmpty(userId)
                ? string.Empty
                : $"@{userId}";

            UserProfileImage = img == null
                ? StyleDefinition.ProfileNone
                : Stores.LoadUserProfileImage(img);
        }
    }

    public class BarHeightEventArgs : EventArgs
    {
        public double NavigationBarHeight { get; set; }
        public double StatusBarHeight { get; set; }
    }
}
