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

using Microsoft.Maui.Controls.Shapes;

using DXLib.Utils;

namespace DXLib.UI.Gestures;

/*
 * Equivalent to DXBorder with the addition of support for up, down, tap, and long press gestures.
 */ 
public class DXBorderGestures : MR.Gestures.Border
{
	/* Constants */
	private const float DefaultElevation = 2;
	
	// Shadow config
	private static readonly Color ShadowColor = Colors.Black;
	private const float ShadowOpacity = 0.5f;
	
	/* Properties */
	public LayoutOptions Horizontal { set => HorizontalOptions = value; }
	public LayoutOptions Vertical { set => VerticalOptions = value; }
	
	// Corner radius (0 for rectangle) 
	public double CornerRadius { get; set; }
	
	// Border thickness (0 for none)
	public double BorderWidth { get; set; }

	// Color of border (NA if no border)
	public Color BorderColor { get; set; }
	
	// Material style elevation/shadow (0 for none)
	public double Elevation { get; set; }

	// Solid color fill within border
	public Color Color { get => BackgroundColor; set => BackgroundColor = value; }
	
	// Reusable shadows
	protected static Shadow DefaultShadow { get; private set; }
	protected static Shadow EmptyShadow { get; private set; }
	
	// Bounds usable BEFORE layout
	public Rect LayoutBounds { get; private set; }
	
	/* Methods */
	public DXBorderGestures()
	{
		// Create shadows once only
		DefaultShadow ??= CreateShadow( ShadowColor, DefaultElevation, ShadowOpacity );
		EmptyShadow ??= CreateShadow( Colors.White, 0, 0.0 );

		Margin = 0;
		Padding = 0;
		
		// Set defaults
		CornerRadius = 0;
		Elevation = 0;
		
		BorderWidth = 0;
		BorderColor = null;
	}
	
	// Post-construction initialization (only required if using radius/border/elevation)
	public virtual void Init()
	{
		Redraw();
	}
	
	// Shorthand for setting dimensions
	public void SetSize( double wd, double ht )
	{
		WidthRequest = wd;
		HeightRequest = ht;
	}

	// Shorthand for setting square/circle dimension
	public virtual void SetSize( double size, bool circle = false )
	{
		SetSize( size, size );

		if ( circle )
		{
			CornerRadius = (size / 2.0);
			UpdateRadius();
		}
	}
	
	// Shorthand for setting margins
	public void SetMargin( double x, double y, double wd, double ht )
	{
		Margin = new Thickness( x, y, wd, ht );
	}
	
	// Shorthand for setting layout options
	public void SetPosition( LayoutOptions horizontal, LayoutOptions vertical )
	{
		Horizontal = horizontal;
		Vertical = vertical;
	}
	
	// Forces redraw of corners/border/shadow
	public virtual void Redraw()
	{
		// Optionally apply corner radius
		if ( CornerRadius > 0 )
		{
			UpdateRadius();
		}
		
		StrokeThickness = BorderWidth;
		
		// Optionally add border outline
		if ( BorderWidth > 0 )
		{
			Stroke = BorderColor;
		}
		
		// Optionally add drop shadow
		Shadow = (Elevation > 0) ? CreateShadow( ShadowColor, Elevation, ShadowOpacity ) : EmptyShadow;
	}

	// Used internally to create shadow with specified configuration
	private static Shadow CreateShadow( Color color, double offset, double opacity )
	{
		return new Shadow
		{
			Brush = new SolidColorBrush( color ),
			Offset = new Point( offset, offset ),
			Radius = (float)(offset * 3),
			Opacity = (float)opacity
		};
	}
	
	// (Re)draws radius with separate value for each corner 
	public void UpdateRadius( CornerRadius radius )
	{
		StrokeShape = new RoundRectangle
		{
			CornerRadius = radius
		};
	}
	
	// (Re)draws corner radius
	private void UpdateRadius()
	{
		UpdateRadius( new CornerRadius( CornerRadius, CornerRadius, CornerRadius, CornerRadius ) );
	}

	/* Layout */

	// Sets bounds of this border within specified layout
	public void SetLayoutBounds( DXAbsoluteGestures layout, double x, double y, double wd, double ht )
	{
		LayoutBounds = new Rect( x, y, wd, ht );
		
		layout.SetBounds( this, LayoutBounds );	
	}

	// Allows special handling for device rotation
	public virtual void Rotate()
	{}

	// Forces layout for current device type/orientation
	public void UpdateLayout()
	{
		UpdateLayout( DXDevice.GetLayoutType() );
	}

	// Gives subclasses opportunity to make type/orientation specific changes
	public virtual void UpdateLayout( LayoutType type )
	{
		switch ( type )
		{
			case LayoutType.Landscape: Landscape(); break;
			case LayoutType.Portrait: Portrait(); break;

			case LayoutType.WideLandscape: WideLandscape(); break;
			case LayoutType.WidePortrait: WidePortrait(); break;

			case LayoutType.MobileLandscape: MobileLandscape(); break;
			case LayoutType.MobilePortrait: MobilePortrait(); break;
			
			default: break;
		}
	}

	// Layout changes specific to each possible size
	protected virtual void Landscape() {}
	protected virtual void Portrait() {}

	protected virtual void WideLandscape() {}
	protected virtual void WidePortrait() {}

	protected virtual void MobileLandscape() {}
	protected virtual void MobilePortrait() {}
}

//
