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

using SkiaSharp;
using SkiaSharp.Views.Maui;
using SkiaSharp.Views.Maui.Controls;

using DXLib.UI;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Draws a scorecard for one team. A scorecard consists of a rounded rectangle and colored title bar as well as a large
 * numeric score. The card can be tapped or long pressed.
 */
public class ScoreCard : SKCanvasView
{
	/* Constants */

	// Long press
	private const int PressDelay = 500;

	// Disabled state
	private readonly Color DisabledColor = DXColors.Light1;

	// Simulate Material drop shadow
	private const float ShadowOffset = 2.0f;
	private const float ShadowBlur = 1.5f;
	public const float ShadowPadding = 5;

	private readonly SKColor ShadowColor = new( 0, 0, 0, 75 );
	
	/* Actions */
	public Action Tapped { get; set; }
	public Action Pressed { get; set; }
	
	/* Properties */
	public int Score { get => Convert.ToInt32( scoreStr ); set { scoreStr = value.ToString( "00" ); Redraw(); } }
	public double ScoreSize { get; set; }

	// Drawing
	public float BarHt { get; set; }

	public Color ScoreColor { get; set; }
	public Color CardColor { get; set; }
	public Color BarColor { get; set; }
	public Color OutlineColor { get; set; }

	public float CornerRadius { get; set; }

	public bool HasShadow { get; set; }
	public bool HasOutline { get; set; }

	// Being used by ScoreSmall?
	public bool IsSmall { get; set; }

	// Text positioning
	public float AdjustX { get; set; }
	public float AdjustY { get; set; }

	// Disabled state
	public bool IsDisabled { set => Disable( value ); }
	public bool ShowDisabled { get; set; }

	/* Fields */
	private string scoreStr;
	private Color cardColor;

	// Long press handling
	private DateTimeOffset? touchDown;
	
	/* Methods */
	public ScoreCard()
	{
		// Defaults
		AdjustX = DXDevice.IsTablet ? 0 : -0.5f;
		AdjustY = 0;

		EnableTouchEvents = true;
		
		// Register for events
		Touch += OnTouch;
		PaintSurface += OnPaintSurface;
	}

	// Toggles disabled state of the card, indicated by color change
	private void Disable( bool disabled )
	{
		cardColor = (disabled && ShowDisabled) ? DisabledColor : CardColor;
		HasShadow = !disabled;

		Redraw();
	}

	// Forces repaint of entire shape
	public void Redraw()
	{
		InvalidateSurface();
	}

	/* Event Callbacks */

	// User touched canvas
	private void OnTouch( object sender, SKTouchEventArgs args )
	{
		// REQUIRED for touch release
		args.Handled = true;
		
		SKTouchAction action = args.ActionType;

		// Tap started
		if ( action == SKTouchAction.Pressed )
		{
			touchDown = DateTimeOffset.Now;
			
			// Released after delay is long press 
			DXTimer.Delay( PressDelay, () =>
			{
				if ( touchDown != null )
				{
					Pressed?.Invoke();
				}
			});
		}
		// Tap ended
		else if ( action == SKTouchAction.Released )
		{
			if ( touchDown != null )
			{
				double elapsed = DateTimeOffset.Now.Subtract( (DateTimeOffset)touchDown ).TotalMilliseconds;
				
				touchDown = null;
				
				// Released before delay is normal tap
				if ( elapsed < PressDelay )
				{
					Tapped?.Invoke();
				}
			}
		}
	}
	
	// Repaint entire shape
	private void OnPaintSurface( object sender, SKPaintSurfaceEventArgs args )
	{
		// Invalid
		if ( string.IsNullOrEmpty( scoreStr ) )
		{
			return;
		}

		SKCanvas canvas = args.Surface.Canvas;

		// Clear to transparent
		canvas.Clear();

		float scale = (float) DXDevice.Scale;

		// Convert between dp and pixels
		canvas.Scale( scale );

		SKSize size = canvas.LocalClipBounds.Size;

		// Must leave transparent margin for drop shadow
		float wd = (size.Width - ShadowPadding - 1);
		float ht = (size.Height - ShadowPadding - 1);

		float centerX = (wd / 2.0f);
		float centerY = (ht / 2.0f);

		// Adjust for outline
		float offset = HasOutline ? 1 : 0;
		float offset2 = (offset * 2);

		// Simulate Material 4dp elevation drop shadow
		using ( SKImageFilter shadow = SKImageFilter.CreateDropShadow( ShadowOffset, ShadowOffset, ShadowBlur, ShadowBlur, ShadowColor ) )
		{
			// Optional outline
			if ( HasOutline )
			{
				using SKPaint outlinePaint = new();
				
				outlinePaint.Style = SKPaintStyle.Fill;
				outlinePaint.Color = OutlineColor.ToSKColor();
				outlinePaint.ImageFilter = HasShadow ? shadow : null;
				outlinePaint.IsAntialias = true;

				canvas.DrawRoundRect( 0, 0, wd, ht, CornerRadius, CornerRadius, outlinePaint );
			}

			// Main card background
			using SKPaint cardPaint = new();
			
			cardPaint.Style = SKPaintStyle.Fill;
			cardPaint.Color = cardColor.ToSKColor();
			cardPaint.ImageFilter = (HasShadow && !HasOutline) ? shadow : null;
			cardPaint.IsAntialias = true;

			canvas.DrawRoundRect( offset, offset, (wd - offset2), (ht - offset2), CornerRadius, CornerRadius, cardPaint );
		}

		// Top color bar
		using SKPaint barPaint = new();
		
		barPaint.Style = SKPaintStyle.Fill;
		barPaint.Color = BarColor.ToSKColor();
		barPaint.IsAntialias = true;
		
		canvas.DrawRoundRect( offset, offset, (wd - offset2), (BarHt * 2), CornerRadius, CornerRadius, barPaint );

		// Cover bar bottom rounded corners
		using SKPaint coverPaint = new();
		
		coverPaint.Style = SKPaintStyle.Fill;
		coverPaint.Color = cardColor.ToSKColor();
		coverPaint.IsAntialias = true;
		
		canvas.DrawRoundRect( offset, BarHt, (wd - offset2), (BarHt * 2), 0, 0, coverPaint );

		// Custom font 
		SKFont font = DXGraphics.GetFont( DXGraphics.Font.OswaldBold );

		font.Embolden = false;
		font.Size = (float)ScoreSize;
		
		// Solid text
		using SKPaint textPaint = new();
		
		textPaint.Style = SKPaintStyle.Fill;
		textPaint.Color = ScoreColor.ToSKColor();
		textPaint.IsAntialias = true;

		// Get dynamic text size
		font.MeasureText( scoreStr, out var textBounds, textPaint );

		// Center text
		float x = (centerX - textBounds.MidX) + AdjustX;
		float y = (centerY + (BarHt / 2.0f) - textBounds.MidY) + AdjustY;

		// Hack to center skinny digits on mobile
		x -= (IsSmall && scoreStr.Contains( '1' )) ? 1 : 0;

		// Draw
		canvas.DrawText( scoreStr, x, y, font, textPaint );
	}
}

//
