using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Pixiview.UI;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace Pixiview
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : AdaptedPage
    {
        public static readonly BindableProperty IllustsProperty = BindableProperty.Create(
            nameof(Illusts), typeof(IllustCollection), typeof(MainPage));
        public static readonly BindableProperty ColumnsProperty = BindableProperty.Create(
            nameof(Columns), typeof(int), typeof(MainPage), 2);
        public static readonly BindableProperty LoadingProperty = BindableProperty.Create(
            nameof(Loading), typeof(bool), typeof(MainPage), propertyChanged: OnLoadingPropertyChanged);

        private static void OnLoadingPropertyChanged(BindableObject obj, object oldValue, object newValue)
        {
            var page = (MainPage)obj;
            var before = (bool)oldValue;
            var now = (bool)newValue;
            if (!page.loaded && now && Stores.NetworkAvailable)
            {
                page.loaded = true;
                Task.Run(page.DoLoadIllusts);
            }
        }

        public IllustCollection Illusts
        {
            get => (IllustCollection)GetValue(IllustsProperty);
            set => SetValue(IllustsProperty, value);
        }
        public int Columns
        {
            get => (int)GetValue(ColumnsProperty);
            set => SetValue(ColumnsProperty, value);
        }
        public bool Loading
        {
            get => (bool)GetValue(LoadingProperty);
            set => SetValue(LoadingProperty, value);
        }

        private readonly ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Configs.MaxThreads };

        private IllustData illustData;
        private bool loaded;

        public MainPage()
        {
            InitializeComponent();

            BindingContext = this;
        }

        public override void OnLoad()
        {
            App.DebugPrint($"folder: {Stores.PersonalFolder}");
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
            Loading = true;
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();

            Connectivity.ConnectivityChanged -= Connectivity_ConnectivityChanged;
        }

        private void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
        {
            if (e.NetworkAccess == NetworkAccess.Internet || e.NetworkAccess == NetworkAccess.ConstrainedInternet)
            {
                Loading = true;
            }
        }

        async void DoLoadIllusts()
        {
            illustData = await Stores.LoadIllustData();
            if (illustData == null)
            {
                App.DebugError("illusts.load", "failed to load illusts data.");
                return;
            }

            var data = illustData.body.page.follow.Select(i =>
            {
                var illust = illustData.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString());
                if (illust == null)
                {
                    return null;
                }
                return new IllustItem
                {
                    ImageUrl = illust.urls.x360 ?? illust.url,
                    Title = illust.illustTitle,
                    IsRestrict = illust.xRestrict == 1,
                    ProfileUrl = illust.profileImageUrl,
                    UserName = illust.userName,
                    Width = illust.width,
                    Height = illust.height,
                    PageCount = illust.pageCount
                };
            }).Where(i => i != null);

            var collection = new IllustCollection(data);
            Illusts = collection;
            Loading = false;

            DoLoadImages(collection);
        }

        void DoLoadImages(IllustCollection collection)
        {
            Parallel.ForEach(collection, parallelOptions, illust =>
            {
                if (!collection.Running)
                {
                    return;
                }
                if (illust.ImageUrl != null)
                {
                    var url = Configs.GetThumbnailUrl(illust.ImageUrl);
                    var image = Stores.LoadThumbnailImage(url);
                    if (image != null)
                    {
                        illust.Image = image;
                    }
                }

                if (illust.ProfileUrl != null)
                {
                    var userImage = Stores.LoadUserProfileImage(illust.ProfileUrl);
                    if (userImage != null)
                    {
                        illust.ProfileImage = userImage;
                    }
                }
            });
        }

        void Page_OrientationChanged(object sender, OrientationEventArgs e)
        {
            switch (e.CurrentOrientation)
            {
                case Orientation.Portrait:
                    Columns = 2;
                    break;
                case Orientation.Unknown:
                case Orientation.PortraitUpsideDown:
                case Orientation.LandscapeLeft:
                case Orientation.LandscapeRight:
                default:
                    Columns = 4;
                    break;
            }
        }

        void NavigationTitle_RightButtonClicked(object sender, EventArgs e)
        {
        }

        void NavigationTitle_LeftButtonClicked(object sender, EventArgs e)
        {
            DisplayAlert("title", "message", "Ok");
        }
    }

    public class IllustCollection : ObservableCollection<IllustItem>
    {
        private static readonly object sync = new object();

        public IllustCollection(IEnumerable<IllustItem> illusts) : base(illusts)
        {
            running = true;
        }

        private bool running;
        public bool Running
        {
            get => running;
            set
            {
                lock (sync)
                {
                    running = value;
                }
            }
        }
    }

    public class IllustItem : BindableObject
    {
        public static readonly BindableProperty ImageProperty = BindableProperty.Create(
            nameof(Image), typeof(ImageSource), typeof(IllustItem));
        public static readonly BindableProperty ProfileImageProperty = BindableProperty.Create(
            nameof(ProfileImage), typeof(ImageSource), typeof(IllustItem));

        public ImageSource Image
        {
            get => (ImageSource)GetValue(ImageProperty);
            set => SetValue(ImageProperty, value);
        }
        public ImageSource ProfileImage
        {
            get => (ImageSource)GetValue(ProfileImageProperty);
            set => SetValue(ProfileImageProperty, value);
        }

        public string ImageUrl { get; set; }
        public string Title { get; set; }
        public bool IsRestrict { get; set; }
        public string ProfileUrl { get; set; }
        public string UserName { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public int PageCount { get; set; }
        public string PageCountText => $"{StyleDefinition.IconLayer} {PageCount}";
        public bool IsPageVisible => PageCount > 1;
    }
}
