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

using DXLib.UI.Alert;

using DXLib.UI.Layout;
using DXLib.UI.Gestures;

using DXLib.UI.Control;
using DXLib.UI.Control.Image;
using DXLib.UI.Control.Button;

using DXLib.Data;
using DXLib.Utils;

namespace DXLib.UI.Form;

/*
 * Control used on all forms providing an image that can be either an icon or photo. The area can cover an arbitrary
 * space in the parent layout and have its own background color. Tapping the image while in edit mode will launch an
 * image selector interface. Help text and tooltip button are also provided.
 */
public class DXFormImage : DXGridGestures
{
	/* Constants */

	// Border config
	private static readonly Color BorderColor = DXColors.Light4;
	private const double BorderWd = 2;
	
	/* Properties */
	public string DefaultIcon { set => imageArea.DefaultIcon = value; }

	// Custom color
	public Color Color { set => SetColor( value ); }

	// Data edited?
	public bool HasChanges { get; private set; }

	/* Fields */
	private readonly DXForm parent;
	private readonly DXImageArea imageArea;

	private readonly DXHorizontalLayout helpLayout;
	private readonly DXLabel helpLbl;
	private readonly DXIconButton helpBtn;

	private DXImageSelector imageSelector;

	/* Methods */
	public DXFormImage( DXForm parent )
	{
		this.parent = parent;

		bool tablet = DXDevice.IsTablet;

		// Spacing
		Padding = 0;
		RowSpacing = 0;
		
		// Underlying image control
		imageArea = new DXImageArea
		{
			Padding = 0,
			Margin = 0,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};
		
		// Layout for help text/tooltip
		helpLayout = new DXHorizontalLayout
		{
			Margin = new Thickness( 0, 10 ),
			Spacing = 10,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Start
		};

		// 'Tap image to edit'
		helpLbl = new DXLabel
		{
			Text = DXString.Get( "form.image" ),
			TextColor = DXColors.Light4,
			Font = DXFonts.Roboto,

			Vertical = LayoutOptions.Center
		};

		// Tooltip button
		helpBtn = new DXIconButton
		{
			Resource = "help_mobile",
			Size = tablet ? 26 : 22,
			IconColor = DXColors.Light4,

			Vertical = LayoutOptions.Center,

			IsSticky = true,
			ButtonTapped = OnHelpTapped
		};

		helpLayout.Add( helpLbl );
		helpLayout.Add( helpBtn );

		// Defaults
		HasChanges = false;
	}

	// Post construction initialization
	public void Init( bool canEdit )
	{
		// Determines if image editable (MUST use opacity to hold space)
		helpLayout.Opacity = canEdit ? 1.0 : 0.0;

		// Required workaround for nested tapping issue
		if ( canEdit )
		{
			Down += OnImageTapped;
		}
	}

	// Used internally to set image area color
	private void SetColor( Color value )
	{
		Color color = value ?? DXImageArea.DefaultColor;

		BackgroundColor = color;
		imageArea.Color = color;
	}

	/* Read */

	// Sets photo image from raw byte array
	public void SetImage( byte[] bytes )
	{
		imageArea.SetImage( bytes );
	}

	// Sets photo image from in-memory image source
	private void SetImage( ImageSource source )
	{
		imageArea.SetImage( source );
	}

	// Sets photo image from remote cloud storage URL
	public void SetImage( string url )
	{
		imageArea.SetImage( url );
	}

	/* Write */

	// Returns current photo (if any) as byte array suitable for persistence
	public async Task<byte[]> GetImage()
	{
		const int size = DXImageArea.ImageSize;

		// @3x dpi for largest screen size/orientation
		return await imageArea.GetImage( size, size );
	}

	/* Event Callbacks */

	// User editing photo
	private void OnImageTapped( object sender, MR.Gestures.DownUpEventArgs args )
	{
		// Make sure only image area tappable
		if ( imageArea.Bounds.Contains( args.Center ) )
		{
			if ( DXData.HasConnection() )
			{
				// Lazy init popup
				imageSelector ??= new DXImageSelector
				{
					ImageSelected = OnImageSelected
				};

				// Show popup anchored to image area
				imageSelector.Show( imageArea, imageArea.HasImage );
			}
			else
			{
				DXAlert.ShowNetworkError( "net.err.image" );
			}
		}
	}

	// User selected or cleared photo
	private void OnImageSelected( ImageSource source )
	{
		// Dismiss
		imageSelector.Hide();

		// Update image
		SetImage( source );
		UpdateLayout();

		HasChanges = true;

		// Enable save button
		parent.IsValid();
	}

	// Show generic help tooltip used on all forms
	private void OnHelpTapped()
	{
		DXTooltip.Show( helpBtn, "form.image" );
	}

	/* Layout */

	// Device/orientation specific layout
	public override void UpdateLayout( LayoutType type )
	{
		ClearAll();

		// Size specific layouts
		base.UpdateLayout( type );
		
		// Do NOT need to update ImageArea here
	}

	// Landscape (4:3)
	protected override void Landscape()
	{
		helpLbl.FontSize = 17;

		const double padding = 24;

		// Image size is column width - padding (4:3 aspect ratio)
		double imageWd = (DXDevice.GetLandscapeWd() * 0.26) - (padding * 2);
		double imageHt = (imageWd * 3.0) / 4.0;

		// 5 rows
		AddFixedRow( 76 );					// 0: pad
		AddFixedRow( BorderWd );			// 1: border
		AddFixedRow( imageHt );				// 2: icon/image
		AddFixedRow( BorderWd );			// 3: border
		AddStarRow();						// 4: help layout, fill

		// 5 columns
		AddStarColumn();					// 0: pad
		AddFixedColumn( BorderWd );			// 1: border
		AddFixedColumn( imageWd );			// 2: icon/image
		AddFixedColumn( BorderWd );			// 3: border
		AddStarColumn();					// 4: pad

		// Border
		Fill( BorderColor, 1, 1, 3, 1 );	// top
		Fill( BorderColor, 3, 1, 1, 3 );	// right
		Fill( BorderColor, 1, 3, 3, 1 );	// bottom
		Fill( BorderColor, 1, 2 );			// left
		
		Add( imageArea, 2, 2 );
		Add( helpLayout, 2, 4 );
	}

	// Portrait (3:4)
	protected override void Portrait()
	{
		helpLbl.FontSize = DXDevice.IsTablet ? 17 : 14;

		const double padding = 24;
		const double topPad = ((padding / 2) + 5);
		
		// Image size is fixed height - padding (4:3 aspect ratio)
		const double imageHt = 250 - (padding + 27 + 15);
		const double imageWd = imageHt * (4.0 / 3.0);

		// 5 rows
		AddFixedRow( topPad );				// 0: pad
		AddFixedRow( BorderWd );			// 1: border
		AddFixedRow( imageHt );				// 2: icon/image
		AddFixedRow( BorderWd );			// 3: border
		AddStarRow();						// 4: help layout

		// 5 columns
		AddStarColumn();					// 0: pad
		AddFixedColumn( BorderWd );			// 1: border
		AddFixedColumn( imageWd );			// 2: icon/image
		AddFixedColumn( BorderWd );			// 3: border
		AddStarColumn();					// 4: pad

		// Border
		Fill( BorderColor, 1, 1, 3, 1 );	// top
		Fill( BorderColor, 3, 1, 1, 3 );	// right
		Fill( BorderColor, 1, 3, 3, 1 );	// bottom
		Fill( BorderColor, 1, 2 );			// left
		
		Add( imageArea, 2, 2 );
		Add( helpLayout, 2, 4 );
	}

	// Mobile landscape
	protected override void MobileLandscape()
	{
		helpLayout.Spacing = 5;

		helpLbl.FontSize = 13;
		helpLbl.Resource = "form.image";

		const double padding = 16;

		// Image size is column width - padding (4:3 aspect ratio)
		double imageWd = (DXDevice.GetLandscapeWd() * 0.24) - (padding * 2);
		double imageHt = (imageWd * 3.0) / 4.0;

		// 5 rows
		AddFixedRow( 50 );					// 0: pad to match header
		AddFixedRow( BorderWd );			// 1: border
		AddFixedRow( imageHt );				// 2: icon/image
		AddFixedRow( BorderWd );			// 3: border
		AddStarRow();						// 4: help layout, fill

		// 5 columns
		AddStarColumn();					// 0: pad
		AddFixedColumn( BorderWd );			// 1: border
		AddFixedColumn( imageWd );			// 2: icon/image
		AddFixedColumn( BorderWd );			// 3: border
		AddStarColumn();					// 4: pad

		// Border
		Fill( BorderColor, 1, 1, 3, 1 );	// top
		Fill( BorderColor, 3, 1, 1, 3 );	// right
		Fill( BorderColor, 1, 3, 3, 1 );	// bottom
		Fill( BorderColor, 1, 2 );			// left

		Add( imageArea, 2, 2 );
		Add( helpLayout, 2, 4 );
	}

	// Mobile portrait
	protected override void MobilePortrait()
	{
		helpLayout.Spacing = 10;

		helpLbl.FontSize = 14;
		helpLbl.Resource = "form.image";

		// Rest same as tablet
		Portrait();
	}
}

//
