/*
 * Copyright (c)2009-2025 DemiVision, LLC. All Rights Reserved. The information
 * herein is the CONFIDENTIAL and PROPRIETARY information of DemiVision, LLC.
 */

using DXLib.UI.Layout;

namespace DXLib.UI.Control.Image;

/*
 * A component used to display an image area, which contains a photo image or a default icon if no photo is specified.
 * The image area can display its own background color and can optionally display a border with internal padding. Photos
 * can be from in-memory image source, raw byte array, or remote URL.
 */
public class DXImageArea : DXGridLayout
{
	/* Constants */
	public static readonly Color DefaultColor = DXColors.Action;
	private static readonly Color DefaultIconColor = DXColors.Light4;

	// Big enough for @3x on most screen sizes
	public const int ImageSize = 640;

	/* Properties */
	public string DefaultIcon { set => SetIcon( value ); }

	// Icon customization
	public Color IconColor { set => UpdateIconColor( value ); }

	// Background color
	public Color Color { get => BackgroundColor; set => BackgroundColor = value; }
	
	// Image currently selected?
	public bool HasImage => (image != null);

	/* Fields */
	private Color iconColor;
	
	// Underlying components
	private DXIcon icon;
	private DXImage image;

	/* Inherited */
	
	// CornerRadius
	// BorderWidth
	// Elevation
	
	/* Bindings */

	// Icon, Image, Color
	public static readonly BindableProperty IconProperty = BindableProperty.Create( "DefaultIcon", typeof( string ), typeof( DXImageArea ), string.Empty, BindingMode.OneWay, null, IconPropertyChanged );
	public static readonly BindableProperty ImageUrlProperty = BindableProperty.Create( "ImageUrl", typeof( string ), typeof( DXImageArea ), string.Empty, BindingMode.OneWay, null, ImageUrlPropertyChanged );
	public static readonly BindableProperty ColorProperty = BindableProperty.Create( "Color", typeof( Color ), typeof( DXImageArea ), DXColors.Action, BindingMode.OneWay, null, ColorPropertyChanged );
	
	/* Methods */
	public DXImageArea()
	{
		Padding = 0;
		Margin = 0;
		
		Horizontal = LayoutOptions.Fill;
		Vertical = LayoutOptions.Fill;
		
		IsClippedToBounds = true;
		
		// Defaults
		IconColor = DefaultIconColor;
	}
	
	// Used to dynamically set size of icon
	public void SetSize( double wd, double ht, double iconScale = 1.0 )
	{
		base.SetSize( wd, ht );
		
		double size = (Math.Min( wd, ht ) * iconScale);
		
		// Icon (square)
		icon?.SetSize( size );
	}

	/* Icon */

	// Displays default icon
	public void SetIcon( string resource )
	{
		if ( resource != null )
		{
			// Icon centered in view
			icon = new DXIcon
			{
				Resource = $"{resource}.png",
				Color = iconColor,
				BackgroundColor = Colors.Transparent,
				
				Margin = 20, 
				Aspect = Aspect.AspectFit,
				
				HorizontalOptions = LayoutOptions.Fill,
				VerticalOptions = LayoutOptions.Fill
			};

			Add( icon, 0, 0  );
		}
	}

	// Used internally to update image area icon color
	private void UpdateIconColor( Color color )
	{
		iconColor = color;

		if ( icon != null )
		{
			icon.Color = color;
		}
	}
	
	/* Image */

	// Returns current photo (if any) as byte array suitable for persistence
	public async Task<byte[]> GetImage( int width, int height )
	{
		return (image == null) ? null : await image.ToByteArray( width, height );
	}

	// Sets photo image from raw byte array
	public void SetImage( byte[] bytes )
	{
		bool hasImage = bytes is { Length: > 0 };

		SetImage( hasImage );

		if ( hasImage )
		{
			image.FromByteArray( bytes );
		}
	}

	// Sets photo image from in-memory image source
	public void SetImage( ImageSource source )
	{
		bool hasImage = (source != null);

		SetImage( hasImage ); 

		if ( hasImage )
		{
			image.FromSource( source );
		}
	}

	// Sets photo image from remote cloud storage URL
	public void SetImage( string url )
	{
		bool hasImage = !string.IsNullOrEmpty( url );

		SetImage( hasImage );

		if ( hasImage )
		{
			image.FromUrl( url );
		}
	}

	// Base functionality for switching to photo mode
	private void SetImage( bool hasImage )
	{
		// Photo always on top
		if ( hasImage )
		{
			if ( image == null )
			{
				// Photo fills view
				image = new DXImage
				{
					Aspect = Aspect.AspectFill,
					
					Horizontal = LayoutOptions.Fill,
					Vertical = LayoutOptions.Fill
				};

				Add( image, 0, 0  );
			}
		}
		// Icon only
		else
		{
			if ( image != null )
			{
				Remove( image );
				image = null;
			}
		}
	}

	/* Dynamic Properties */

	// Icon binding changed, update value
	private static void IconPropertyChanged( BindableObject bindable, object oldValue, object newValue )
	{
		DXImageArea imageArea = bindable as DXImageArea;

		imageArea!.DefaultIcon = (string)newValue;
	}

	// Image binding changed, update value
	private static void ImageUrlPropertyChanged( BindableObject bindable, object oldValue, object newValue )
	{
		DXImageArea imageArea = bindable as DXImageArea;
		string imageUrl = (string)newValue;

		imageArea!.SetImage( imageUrl );
	}

	// Color binding changed, update value
	private static void ColorPropertyChanged( BindableObject bindable, object oldValue, object newValue )
	{
		DXImageArea imageArea = bindable as DXImageArea;
		Color color = (Color)newValue;

		imageArea!.Color = color;
	}
}

//
