using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Pixiview.Resources;
using Pixiview.UI;
using Pixiview.UI.Theme;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace Pixiview.Illust
{
    [QueryProperty("IllustId", "id")]
    public partial class ViewIllustPage : AdaptedPage
    {
        #region - Properties -
        public static readonly BindableProperty FavoriteIconProperty = BindableProperty.Create(
            nameof(FavoriteIcon), typeof(ImageSource), typeof(ViewIllustPage));

        public ImageSource FavoriteIcon
        {
            get => (ImageSource)GetValue(FavoriteIconProperty);
            set => SetValue(FavoriteIconProperty, value);
        }

        public static readonly BindableProperty IllustsProperty = BindableProperty.Create(
            nameof(Illusts), typeof(IllustDetailItem[]), typeof(ViewIllustPage));
        public static readonly BindableProperty IsPageVisibleProperty = BindableProperty.Create(
            nameof(IsPageVisible), typeof(bool), typeof(ViewIllustPage));
        public static readonly BindableProperty PagePositionTextProperty = BindableProperty.Create(
            nameof(PagePositionText), typeof(string), typeof(ViewIllustPage));
        public static readonly BindableProperty CurrentPageProperty = BindableProperty.Create(
            nameof(CurrentPage), typeof(int), typeof(ViewIllustPage), propertyChanged: OnCurrentPagePropertyChanged);
        public static readonly BindableProperty IsScrollAnimatedProperty = BindableProperty.Create(
            nameof(IsScrollAnimated), typeof(bool), typeof(ViewIllustPage), true);

        public IllustDetailItem[] Illusts
        {
            get => (IllustDetailItem[])GetValue(IllustsProperty);
            set => SetValue(IllustsProperty, value);
        }
        public bool IsPageVisible
        {
            get => (bool)GetValue(IsPageVisibleProperty);
            set => SetValue(IsPageVisibleProperty, value);
        }
        public string PagePositionText
        {
            get => (string)GetValue(PagePositionTextProperty);
            set => SetValue(PagePositionTextProperty, value);
        }
        public int CurrentPage
        {
            get => (int)GetValue(CurrentPageProperty);
            set => SetValue(CurrentPageProperty, value);
        }
        public bool IsScrollAnimated
        {
            get => (bool)GetValue(IsScrollAnimatedProperty);
            set => SetValue(IsScrollAnimatedProperty, value);
        }

        private static void OnCurrentPagePropertyChanged(BindableObject obj, object old, object @new)
        {
            var page = (ViewIllustPage)obj;
            var index = (int)@new;
            var items = page.Illusts;
            var length = items.Length;
            page.PagePositionText = $"{index + 1}/{length}";
        }

        public static readonly BindableProperty AnimeStatusProperty = BindableProperty.Create(
            nameof(AnimeStatus), typeof(string), typeof(ViewIllustPage), StyleDefinition.IconPlay);
        public static readonly BindableProperty IsAnimateSliderVisibleProperty = BindableProperty.Create(
            nameof(IsAnimateSliderVisible), typeof(bool), typeof(ViewIllustPage));
        public static readonly BindableProperty IsAnimateSliderEnabledProperty = BindableProperty.Create(
            nameof(IsAnimateSliderEnabled), typeof(bool), typeof(ViewIllustPage));
        public static readonly BindableProperty CurrentAnimeFrameProperty = BindableProperty.Create(
            nameof(CurrentAnimeFrame), typeof(double), typeof(ViewIllustPage), propertyChanged: OnCurrentAnimeFramePropertyChanged);
        public static readonly BindableProperty MaximumFrameProperty = BindableProperty.Create(
            nameof(MaximumFrame), typeof(double), typeof(ViewIllustPage), 1.0);

        private static void OnCurrentAnimeFramePropertyChanged(BindableObject obj, object old, object @new)
        {
            var page = (ViewIllustPage)obj;
            if (page.ugoira != null && page.IsAnimateSliderEnabled)
            {
                var frame = (double)@new;
                page.ugoira.ToggleFrame((int)frame);
            }
        }

        public string AnimeStatus
        {
            get => (string)GetValue(AnimeStatusProperty);
            set => SetValue(AnimeStatusProperty, value);
        }
        public bool IsAnimateSliderVisible
        {
            get => (bool)GetValue(IsAnimateSliderVisibleProperty);
            set => SetValue(IsAnimateSliderVisibleProperty, value);
        }
        public bool IsAnimateSliderEnabled
        {
            get => (bool)GetValue(IsAnimateSliderEnabledProperty);
            set => SetValue(IsAnimateSliderEnabledProperty, value);
        }
        public double CurrentAnimeFrame
        {
            get => (double)GetValue(CurrentAnimeFrameProperty);
            set => SetValue(CurrentAnimeFrameProperty, value);
        }
        public double MaximumFrame
        {
            get => (double)GetValue(MaximumFrameProperty);
            set => SetValue(MaximumFrameProperty, value);
        }

        public static readonly BindableProperty ProgressVisibleProperty = BindableProperty.Create(
            nameof(ProgressVisible), typeof(bool), typeof(ViewIllustPage));

        public bool ProgressVisible
        {
            get => (bool)GetValue(ProgressVisibleProperty);
            set => SetValue(ProgressVisibleProperty, value);
        }
        #endregion

        public IllustItem IllustItem { get; private set; }

        private readonly ImageSource fontIconLove;
        private readonly ImageSource fontIconNotLove;
        private readonly ImageSource fontIconCircleLove;
        private bool favoriteChanged;
        private IllustUgoiraData ugoiraData;
        private Ugoira ugoira;
        private ParallelTask task;

        private readonly object sync = new object();
        private int downloaded = 0;
        private int pageCount;
        private bool isPreloading;

        public ViewIllustPage(IllustItem illust)
        {
            IllustItem = illust;

            fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
            fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove];
            fontIconCircleLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconCircleLove];

            if (illust != null)
            {
                pageCount = illust.PageCount;
                RefreshInformation(illust, pageCount);
            }
            Resources.Add("carouselView", GetCarouseTemplate());

            BindingContext = this;
            InitializeComponent();

            if (illust != null)
            {
                LoadIllust(illust);
            }
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            Screen.SetHomeIndicatorAutoHidden(Shell.Current, true);
        }

        protected override void OnDisappearing()
        {
            Screen.SetHomeIndicatorAutoHidden(Shell.Current, false);
            base.OnDisappearing();

            if (ugoira != null)
            {
                IllustItem.IsPlaying = false;
                ugoira.FrameChanged -= OnUgoiraFrameChanged;
                ugoira.TogglePlay(false);
                ugoira.Dispose();
                ugoira = null;
            }

            if (favoriteChanged)
            {
                Stores.SaveFavoritesIllusts();
            }
        }

        public override void OnUnload()
        {
            if (task != null)
            {
                task.Dispose();
                task = null;
            }
        }

#if __IOS__
        protected override void OnPageTopMarginChanged(Thickness old, Thickness @new)
        {
            var illusts = Illusts;
            if (illusts != null)
            {
                for (var i = 0; i < illusts.Length; i++)
                {
                    illusts[i].TopPadding = @new;
                }
            }
        }
#endif

        private DataTemplate GetCarouseTemplate()
        {
            return new DataTemplate(() =>
            {
                // image
                var image = new Image
                {
                    HorizontalOptions = LayoutOptions.Fill,
                    VerticalOptions = LayoutOptions.Fill,
                    Aspect = Aspect.AspectFit
                }
                .Binding(Image.SourceProperty, nameof(IllustDetailItem.Image));

                // downloading
                var downloading = new Frame
                {
                    HasShadow = false,
                    Margin = default,
                    Padding = new Thickness(20),
                    CornerRadius = 8,
                    HorizontalOptions = LayoutOptions.Center,
                    VerticalOptions = LayoutOptions.Center,
                    Content = new ActivityIndicator()
                        .Binding(IsVisibleProperty, nameof(IllustDetailItem.Loading))
                        .Binding(ActivityIndicator.IsRunningProperty, nameof(IllustDetailItem.Loading))
                        .DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.WindowColor)
                }
                .Binding(IsVisibleProperty, nameof(IllustDetailItem.Loading))
                .DynamicResource(BackgroundColorProperty, ThemeBase.MaskColor);

                // loading original
                var original = new ActivityIndicator
                {
                    Margin = new Thickness(10),
                    HorizontalOptions = LayoutOptions.Start,
                    VerticalOptions = LayoutOptions.Start
                }
                .Binding(IsVisibleProperty, nameof(IllustDetailItem.Downloading))
                .Binding(ActivityIndicator.IsRunningProperty, nameof(IllustDetailItem.Downloading))
                .DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.TextColor);

                var tap = new TapGestureRecognizer();
                tap.Tapped += Image_Tapped;
                var tapPrevious = new TapGestureRecognizer();
                tapPrevious.Tapped += TapPrevious_Tapped;
                var tapNext = new TapGestureRecognizer();
                tapNext.Tapped += TapNext_Tapped;

                var grid = new Grid
                {
                    Children =
                    {
                        // image
                        image,

                        // tap holder
                        new Grid
                        {
                            RowDefinitions =
                            {
                                new RowDefinition { Height = new GridLength(.3, GridUnitType.Star) },
                                new RowDefinition { Height = new GridLength(.4, GridUnitType.Star) },
                                new RowDefinition { Height = new GridLength(.3, GridUnitType.Star) }
                            },
                            Children =
                            {
                                new Label { GestureRecognizers = { tapPrevious } },
                                new Label { GestureRecognizers = { tap } }.GridRow(1),
                                new Label { GestureRecognizers = { tapNext } }.GridRow(2)
                            }
                        },

                        // downloading
                        downloading,

                        // loading original
                        original
                    }
                };
#if __IOS__
                grid.SetBinding(Xamarin.Forms.Layout.PaddingProperty, nameof(IllustDetailItem.TopPadding));
#endif
                return grid;
            });
        }

        private void LoadIllust(IllustItem illust)
        {
            if (illust == null)
            {
                return;
            }

            var items = new IllustDetailItem[illust.PageCount];

#if __IOS__
            var topMargin = PageTopMargin;
#endif
            for (var i = 0; i < items.Length; i++)
            {
                items[i] = new IllustDetailItem
                {
#if __IOS__
                    TopPadding = topMargin,
#endif
                    Id = illust.Id
                };
                if (i == 0)
                {
                    items[i].Loading = true;
                    items[i].Image = illust.Image;
                }
            }

            Illusts = items;
            Task.Run(() => DoLoadImages());
        }

        private void DoLoadImages(bool force = false)
        {
            var illustItem = IllustItem;
            var pages = Stores.LoadIllustPageData(illustItem.Id, out string error, force);
            if (pages == null)
            {
                App.DebugError("illustPage.load", $"failed to load illust page data, id: {illustItem.Id}");
                if (error != null)
                {
                    MainThread.BeginInvokeOnMainThread(() =>
                    {
                        DisplayAlert(ResourceHelper.Title, error, ResourceHelper.Ok);
                    });
                }
                return;
            }
            var items = Illusts;
            var reload = false;
            if (pages.body.Length > items.Length)
            {
#if DEBUG
                App.DebugPrint($"local page count ({items.Length}) is not equals the remote one ({pages.body.Length})");
#endif
                var tmp = new IllustDetailItem[pages.body.Length];
                items.CopyTo(items, 0);
#if __IOS__
                var topMargin = PageTopMargin;
#endif
                for (var i = items.Length; i < tmp.Length; i++)
                {
                    tmp[i] = new IllustDetailItem
                    {
                        Id = illustItem.Id,
#if __IOS__
                        TopPadding = topMargin,
#endif
                        Loading = i == 0
                    };
                }
                Illusts = items = tmp;
                reload = true;
            }

            for (var i = 0; i < items.Length; i++)
            {
                var item = items[i];
                var p = pages.body[i];
                item.PreviewUrl = p.urls.regular;
                item.OriginalUrl = p.urls.original;

                if (i == 0 && illustItem.ImageUrl == null)
                {
                    // maybe open from a link
                    reload = true;
                }
            }

            if (reload)
            {
                DoForcePreload(false);
            }

            if (task != null)
            {
                task.Dispose();
                task = null;
            }
            task = ParallelTask.Start("view.illusts", 0, items.Length, Configs.MaxPageThreads, i =>
            {
                DoLoadImage(i);
                return true;
            });

            if (illustItem.IsAnimeVisible)
            {
                // anime
                ugoiraData = Stores.LoadIllustUgoiraData(illustItem.Id);
                if (ugoiraData != null && ugoiraData.body != null)
                {
                    var length = ugoiraData.body.frames.Length;
                    MaximumFrame = length > 0 ? length : 1;
                }
            }
        }

        private void DoLoadImage(int index, bool force = false)
        {
            var items = Illusts;
            if (index < 0 || (!force && index >= items.Length))
            {
                App.DebugPrint($"invalid index: {index}");
                return;
            }

            var item = items[index];
            if (index > 0 && !force)
            {
                if (item.Loading || item.Image != null)
                {
#if DEBUG
                    App.DebugPrint($"skipped, loading or already loaded, index: {index}, loading: {item.Loading}");
#endif
                    return;
                }
            }
            item.Loading = true;
            var image = Stores.LoadPreviewImage(item.PreviewUrl, force: force);
            if (image != null)
            {
                item.Image = image;
                if(index == 0)
                {
                    IllustItem.Image = image;
                }
            }
            item.Loading = false;
            RefreshProgress();
        }

        private void RefreshProgress()
        {
            if (pageCount <= 1)
            {
                return;
            }

            lock (sync)
            {
                downloaded++;
            }
            if (downloaded >= pageCount)
            {
                MainThread.BeginInvokeOnMainThread(async () =>
                {
                    ViewExtensions.CancelAnimations(progress);
                    await progress.ProgressTo(1, 250, Easing.CubicIn);
                    await progress.FadeTo(0, easing: Easing.CubicIn);
                    ProgressVisible = false;
                });
            }
            else
            {
                var val = downloaded / (float)pageCount;
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    ViewExtensions.CancelAnimations(progress);
                    progress.ProgressTo(val, 250, Easing.CubicIn);
                });
            }

        }

        private void TapPrevious_Tapped(object sender, EventArgs e)
        {
            var index = CurrentPage;
            if (index > 0)
            {
                IsScrollAnimated = false;
                CurrentPage = index - 1;
                IsScrollAnimated = true;
            }
        }

        private void TapNext_Tapped(object sender, EventArgs e)
        {
            var index = CurrentPage;
            var illusts = Illusts;
            if (illusts != null && index < illusts.Length - 1)
            {
                IsScrollAnimated = false;
                CurrentPage = index + 1;
                IsScrollAnimated = true;
            }
        }

        private async void Favorite_Clicked(object sender, EventArgs e)
        {
            var favorites = Stores.Favorites;
            var illust = IllustItem;
            var index = favorites.FindIndex(i => i.Id == illust.Id);
            var bookmarkId = illust.BookmarkId;
            bool add = index < 0 && bookmarkId == null;
            if (add)
            {
                illust.IsFavorite = true;
                illust.FavoriteDateUtc = DateTime.UtcNow;
                favorites.Insert(0, illust);
                FavoriteIcon = fontIconLove;
            }
            else
            {
                if (index >= 0)
                {
                    var item = favorites[index];
                    if (bookmarkId == null && item.BookmarkId != null)
                    {
                        bookmarkId = item.BookmarkId;
                        illust.BookmarkId = bookmarkId;
                    }
                    favorites.RemoveAt(index);
                }
                illust.IsFavorite = false;
                FavoriteIcon = bookmarkId == null ?
                    fontIconNotLove :
                    fontIconCircleLove;
            }
            favoriteChanged = true;

            if (Configs.SyncFavType == SyncType.None)
            {
                return;
            }
            if (Configs.Cookie == null)
            {
                return;
            }
            if (!add && string.IsNullOrEmpty(bookmarkId))
            {
                return;
            }
            if (Configs.SyncFavType == SyncType.Prompt)
            {
                var ok = await DisplayAlert(
                    ResourceHelper.Title,
                    ResourceHelper.ConfirmSyncFavorite,
                    ResourceHelper.Yes,
                    ResourceHelper.No);
                if (!ok)
                {
                    return;
                }
            }

            if (add)
            {
                var id = await Task.Run(() => Stores.AddBookmark(illust.Id));
                if (id != null)
                {
                    bookmarkId = id;
                    illust.BookmarkId = bookmarkId;
                    FavoriteIcon = fontIconCircleLove;
                }
            }
            else
            {
                var result = await Task.Run(() => Stores.DeleteBookmark(bookmarkId));
                if (result)
                {
                    FavoriteIcon = fontIconNotLove;
                }
            }

            // immediately save after changing remote
            Stores.SaveFavoritesIllusts();
            favoriteChanged = false;
        }

        private void Image_Tapped(object sender, EventArgs e)
        {
            if (ugoiraData == null)
            {
                return;
            }
            var illustItem = IllustItem;

            if (ugoira != null)
            {
                var playing = !ugoira.IsPlaying;
                AnimeStatus = playing ? StyleDefinition.IconPause : StyleDefinition.IconPlay;
                IsAnimateSliderEnabled = !playing;
                ugoira.TogglePlay(playing);
                illustItem.IsPlaying = playing;
            }
            else if (((VisualElement)sender).BindingContext is IllustDetailItem item)
            {
                if (illustItem.IsPlaying || !illustItem.IsAnimeVisible)
                {
                    return;
                }

                ugoira = new Ugoira(ugoiraData, item);
                ugoira.FrameChanged += OnUgoiraFrameChanged;
                AnimeStatus = StyleDefinition.IconPause;
                illustItem.IsPlaying = true;
                ugoira.TogglePlay(true);
            }
        }

        private void OnUgoiraFrameChanged(object sender, UgoiraEventArgs e)
        {
            e.DetailItem.Image = e.Image;
            CurrentAnimeFrame = e.FrameIndex;
        }

        private void RefreshInformation(IllustItem item, int count)
        {
            Title = item.Title;
            FavoriteIcon = item.BookmarkId != null ?
                fontIconCircleLove :
                Stores.Favorites.Any(i => i.Id == item.Id) ?
                    fontIconLove :
                    fontIconNotLove;
            IsAnimateSliderVisible = item.IsAnimeVisible;
            if (count > 1)
            {
                IsPageVisible = true;
                ProgressVisible = true;
                PagePositionText = $"1/{count}";
            }
        }

        private void DoForcePreload(bool force)
        {
            isPreloading = true;
            var illustItem = IllustItem;
            // force to reload
            var preload = Stores.LoadIllustPreloadData(illustItem.Id, force);
            if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust))
            {
                illust.CopyToItem(illustItem);
                pageCount = illustItem.PageCount;
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    RefreshInformation(illustItem, pageCount);
                });
                if (preload.user.TryGetValue(illust.userId, out var user))
                {
                    illustItem.ProfileUrl = user.image;
                }
            }
            isPreloading = false;
        }

        private void Refresh_Clicked(object sender, EventArgs e)
        {
            if (isPreloading)
            {
                return;
            }
            Task.Run(() =>
            {
                DoForcePreload(true);
                DoLoadImage(CurrentPage, true);
            });
        }

        private async void More_Clicked(object sender, EventArgs e)
        {
            int p = CurrentPage;
            var illusts = Illusts;
            if (illusts == null || p < 0 || p >= illusts.Length)
            {
                return;
            }

            var item = illusts[p];
            List<string> extras = new List<string>();

            var share = ResourceHelper.Share;
            var preview = Stores.GetPreviewImagePath(item.PreviewUrl);
            if (preview != null)
            {
                extras.Add(share);
            }

            var userDetail = ResourceHelper.UserDetail;
            extras.Add(userDetail);

            var related = ResourceHelper.RelatedIllusts;
            extras.Add(related);

#if __IOS__
            var exportVideo = ResourceHelper.ExportVideo;
            if (IsAnimateSliderVisible)
            {
                extras.Add(exportVideo);
            }
#endif

            var saveOriginal = ResourceHelper.SaveOriginal;
            var illustItem = IllustItem;
            var result = await DisplayActionSheet(
                $"{illustItem.Title} (id: {illustItem.Id})",
                ResourceHelper.Cancel,
                saveOriginal,
                extras.ToArray());

            if (result == saveOriginal)
            {
                SaveOriginalImage(item);
            }
            else if (result == share)
            {
                await Share.RequestAsync(new ShareFileRequest
                {
                    Title = illustItem.Title,
                    File = new ShareFile(preview)
                });
            }
            else if (result == userDetail)
            {
                var page = new UserIllustPage(illustItem);
                await Navigation.PushAsync(page);
            }
            else if (result == related)
            {
                var page = new RelatedIllustsPage(illustItem);
                await Navigation.PushAsync(page);
            }
#if __IOS__
            else if (result == exportVideo)
            {
                ExportVideo();
            }
#endif
        }

#if __IOS__
        private async void ExportVideo()
        {
            string msg = ResourceHelper.CantExportVideo;

            if (ugoira != null && ugoiraData != null && ugoiraData.body != null)
            {
                if (Stores.CheckUgoiraVideo(ugoiraData.body.originalSrc))
                {
                    var flag = await DisplayAlert(ResourceHelper.Operation,
                        ResourceHelper.AlreadySavedVideo,
                        ResourceHelper.Yes,
                        ResourceHelper.No);
                    if (!flag)
                    {
                        return;
                    }
                }

                var status = await Permissions.CheckStatusAsync<Permissions.Photos>();
                if (status != PermissionStatus.Granted)
                {
                    status = await Permissions.RequestAsync<Permissions.Photos>();
                    if (status != PermissionStatus.Granted)
                    {
                        App.DebugPrint("access denied to gallery.");
                        return;
                    }
                }

                var success = await Task.Run(ugoira.ExportVideo);   // ugoira.ExportGif
                if (success != null)
                {
#if DEBUG
                    msg = ResourceHelper.ExportSuccess;
#else
                    var result = await FileStore.SaveVideoToGalleryAsync(success);

                    msg = result ?? ResourceHelper.ExportSuccess;
#endif
                }
            }

            await DisplayAlert(ResourceHelper.Title, msg, ResourceHelper.Ok);
        }
#endif

        private async void SaveOriginalImage(IllustDetailItem item)
        {
            if (Stores.CheckIllustImage(item.OriginalUrl))
            {
                var flag = await DisplayAlert(ResourceHelper.Operation,
                    ResourceHelper.AlreadySavedQuestion,
                    ResourceHelper.Yes,
                    ResourceHelper.No);
                if (!flag)
                {
                    return;
                }
            }

            var status = await Permissions.CheckStatusAsync<Permissions.Photos>();
            if (status != PermissionStatus.Granted)
            {
                status = await Permissions.RequestAsync<Permissions.Photos>();
                if (status != PermissionStatus.Granted)
                {
                    App.DebugPrint("access denied to gallery.");
                    return;
                }
            }

            if (item == null || item.Downloading)
            {
                return;
            }
            item.Downloading = true;
            _ = Task.Run(() => DoLoadOriginalImage(item));
        }

        private void DoLoadOriginalImage(IllustDetailItem item)
        {
            var image = Stores.LoadIllustImage(item.OriginalUrl);
            if (image != null)
            {
                MainThread.BeginInvokeOnMainThread(async () =>
                {
                    var result = await FileStore.SaveImageToGalleryAsync(image);

                    string message = result ?? ResourceHelper.SaveSuccess;
                    await DisplayAlert(ResourceHelper.Title, message, ResourceHelper.Ok);
                });
            }
            item.Downloading = false;
        }
    }

    public class IllustDetailItem : BindableObject
    {
        public static readonly BindableProperty ImageProperty = BindableProperty.Create(
            nameof(Image), typeof(ImageSource), typeof(IllustDetailItem));
        public static readonly BindableProperty LoadingProperty = BindableProperty.Create(
            nameof(Loading), typeof(bool), typeof(IllustDetailItem));
        public static readonly BindableProperty DownloadingProperty = BindableProperty.Create(
            nameof(Downloading), typeof(bool), typeof(IllustDetailItem));
#if __IOS__
        public static readonly BindableProperty TopPaddingProperty = BindableProperty.Create(
            nameof(TopPadding), typeof(Thickness), typeof(IllustDetailItem));

        public Thickness TopPadding
        {
            get => (Thickness)GetValue(TopPaddingProperty);
            set => SetValue(TopPaddingProperty, value);
        }
#endif

        public ImageSource Image
        {
            get => (ImageSource)GetValue(ImageProperty);
            set => SetValue(ImageProperty, value);
        }
        public bool Loading
        {
            get => (bool)GetValue(LoadingProperty);
            set => SetValue(LoadingProperty, value);
        }
        public bool Downloading
        {
            get => (bool)GetValue(DownloadingProperty);
            set => SetValue(DownloadingProperty, value);
        }
        public string Id { get; set; }
        public string PreviewUrl { get; set; }
        public string OriginalUrl { get; set; }
    }
}
