using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Android.Graphics.Drawables;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using Xunit;
using static Microsoft.Maui.DeviceTests.AssertHelpers;

namespace Microsoft.Maui.DeviceTests
{
	public partial class ImageTests
	{
		const string coffeeBase64 = " ";
		const string booksBase64 = " ";

		[Fact]
		public async Task CachingDisabledForImagesLoadViaInputStreams()
		{
			await InvokeOnMainThreadAsync(async () =>
			{
				var image1 = ImageSource.FromStream(() => new TestMemoryStream(Convert.FromBase64String(coffeeBase64)));
				var image2 = ImageSource.FromStream(() => new TestMemoryStream(Convert.FromBase64String(booksBase64)));

				var platformImage1 = await image1.GetPlatformImageAsync(MauiContext);
				var platformImage2 = await image2.GetPlatformImageAsync(MauiContext);

				var bitmapDrawable1 = Assert.IsType<BitmapDrawable>(platformImage1.Value);
				var bitmapDrawable2 = Assert.IsType<BitmapDrawable>(platformImage2.Value);

				// If Glide is using caching for images loaded from streams, then the second image will
				// match the first image (because the second image load attempt will return the cached image)

				// So we assert that the images are _not_ equal to ensure that caching is _not_ turned on for
				// image streams.
				await bitmapDrawable1.Bitmap.AssertNotEqualAsync(bitmapDrawable2.Bitmap);
			});
		}

		[Fact]
		public async Task ImageSetFromStreamRenders()
		{
			SetupBuilder();
			var layout = new VerticalStackLayout();

			using var stream = GetType().Assembly.GetManifestResourceStream("red-embedded.png");

			var image = new Image
			{
				Source = ImageSource.FromStream(() => stream)
			};

			layout.Add(image);

			await InvokeOnMainThreadAsync(async () =>
			{
				var handler = CreateHandler<LayoutHandler>(layout);
				var rootView = handler.ToPlatform();

				await rootView.AttachAndRun(async () =>
				{
					await image.WaitUntilLoaded();
					await rootView.AssertContainsColor(Colors.Red, MauiContext);
				});
			});
		}
	}

	// This subclass of memory stream is deliberately set up to trick Glide into using the cached image
	// after the first image is loaded. See https://github.com/dotnet/maui/issues/8676#issuecomment-1416183584 and
	// https://github.com/dotnet/maui/pull/13111#issuecomment-1416214847 for context.
	class TestMemoryStream : MemoryStream
	{
		public TestMemoryStream(byte[] data) : base(data) { }

		public override string ToString()
		{
			return "TestMemoryStream";
		}

		public override int GetHashCode()
		{
			return 42;
		}

		public override bool Equals(object obj)
		{
			return true;
		}
	}
}
