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

using System.Collections;
using System.Globalization;
using System.ComponentModel;

using Syncfusion.Maui.Data;
using Syncfusion.Maui.DataGrid;
using Syncfusion.Maui.DataGrid.Helper;

using DXLib.UI;
using DXLib.UI.Control;

namespace iStatVball3;

/*
 * Provides custom styling for SfDataGrid (colors, fonts, etc).
 */
public class GridStyle : DataGridStyle
{
	/* Methods */
	public GridStyle( Grid grid )
	{
		// AlternateRowBackground set in ColorConverter 

		// Grid lines
		GridLineStrokeThickness = 1;
		GridLineColor = DXColors.Dark3;

		// Column resize
		ColumnResizingIndicatorColor = DXColors.Action;
		
		// Header border
		HeaderRowBackground = DXColors.Accent1;
		HeaderGridLineStrokeThickness = 1;
		HeaderGridLineColor = DXColors.Dark1;

		double textSize = grid.TextSize;
		
		// Header font
		HeaderRowFontFamily = DXFonts.Roboto;
		HeaderRowFontAttributes = FontAttributes.Bold;
		HeaderRowFontSize = textSize;
		
		// Row font (background color dynamic)
		RowFontFamily = DXFonts.Roboto;
		RowFontAttributes = FontAttributes.None;
		RowFontSize = textSize;
		
		// Stacked header font
		StackedHeaderRowBackground = DXColors.Accent1;
		StackedHeaderRowFontFamily = DXFonts.Roboto;
		StackedHeaderRowFontAttributes = FontAttributes.Bold;
		StackedHeaderRowFontSize = textSize;
		
		// Unbound total row (font attributes set in FontConverter)
		UnboundRowBackground = DXColors.Accent1;
		UnboundRowFontFamily = DXFonts.Roboto;
		UnboundRowFontSize = textSize;

		// Caption summary row
		CaptionSummaryRowBackground = DXColors.Accent2;
		CaptionSummaryRowFontFamily = DXFonts.Roboto;
		CaptionSummaryRowFontAttributes = FontAttributes.None;
		CaptionSummaryRowFontSize = textSize;
	}
}

/*
 * Custom aggregate used to add dimension label to caption summary rows.
 */
public class GridLabelAggregate : ISummaryAggregate
{
	public string Label { get; set; }

	// Syncfusion boilerplate used to return label aggregate
	public Action<IEnumerable,string,PropertyDescriptor> CalculateAggregateFunc()
	{
		return ( items, _, desc ) =>
		{
			if ( items is IEnumerable<DataMetrics> metrics )
			{
				// Label is outer dimension
				if ( desc.Name == "Label" )
				{
					Label = metrics.First()?.TypeLabel;
				}
			}
		};
	}
}

/*
 * ColorConverter used to dynamically define background color for particular grid row/column.
 */
public class GridColorConverter : IValueConverter
{
	// Returns correct background color for specified cell
	object IValueConverter.Convert( object value, Type type, object parameter, CultureInfo culture )
	{
		if ( value is DataGridCell cell )
		{
			if ( parameter is Grid grid )
			{
				if ( cell.DataColumn != null )
				{
					int rowIndex = cell.DataColumn.RowIndex;
					int colIndex = cell.DataColumn.ColumnIndex;
					int rowCount = grid.GetRowCount(); 

					bool lastRow = (rowIndex == (rowCount + (grid.IsStacked ? 1 : 0)));

					// Unbound (total) row highlighted
					if ( lastRow && !grid.IsStatic )
					{
						return DXColors.Accent1;
					}

					// Any column (other than first) can have special focus color
					if ( !grid.HasInner )
					{
						IList<JsonColumn> columns = grid.Json.Columns;
						JsonColumn column = null;

						int count = grid.Json.Columns.Count;

						// Multi-dimensional grid must account for indent column
						if ( grid.HasInner && (colIndex > 1) && (colIndex < (columns.Count + 2)) )
						{
							int index = (colIndex - 2);

							if ( index < count )
							{
								column = columns[ index ];
							}
						}
						// Normal grid
						else if ( colIndex > 0 )
						{
							int index = grid.IsStatic ? colIndex : (colIndex - 1);

							if ( index < count )
							{
								column = columns[ index ];
							}
						}

						// Apply styling
						if ( column is { Focus: true } )
						{
							return DXColors.Accent2;
						}
					}

					// Alternating row color
					return ((rowIndex % 2) == 0) ? DXColors.Light2 : DXColors.Light4;
				}
			}
		}

		// Default
		return DXColors.Light4;
	}

	// NA
	public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
	{
		return null;
	}
}

/*
 * FontConverter used to dynamically apply bold font attribute to unbound rows as well as to columns marked as Focused
 * in external JSON definition.
 */
public class GridFontConverter : IValueConverter
{
	// Returns correct font attribute for specified cell
	public object Convert( object value, Type type, object parameter, CultureInfo culture )
	{
		if ( value is DataGridCell { DataColumn: not null } cell )
		{
			if ( parameter is Grid grid )
			{
				JsonGrid jsonGrid = grid.Json;

				// Must set unbound rows here (FontConverter overrides UnboundRowFontAttributes)
				int rowIndex = cell.DataColumn.RowIndex;

				if ( grid.IsUnboundRow( rowIndex ) )
				{
					return FontAttributes.Bold;
				}
				
				// Must account for static player column (and group indent)
				int colIndex = (cell.DataColumn.ColumnIndex - grid.GroupColumnDescriptions.Count - 1);

				if ( (colIndex >= 0) && (colIndex < jsonGrid.Columns.Count) )
				{
					JsonColumn jsonColumn = jsonGrid.Columns[ colIndex ];

					// Focused columns are bold
					return jsonColumn.Focus ? FontAttributes.Bold : FontAttributes.None;
				}
			}
		}
		
		return FontAttributes.None;
	}

	// NA
	public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
	{
		return null;
	}
}

/*
 * Template selector used to select custom up/down sort icon.
 */
public class GridSortSelector : DataTemplateSelector
{
	/* Properties */
	public DataTemplate Ascending { get; set; }
	public DataTemplate Descending { get; set; }

	/* Methods */
	protected override DataTemplate OnSelectTemplate( object item, BindableObject container )
	{
		if ( item is SortColumnDescription description )
		{
			return (description.SortDirection == ListSortDirection.Ascending) ? Ascending : Descending;
		}

		return null;
	}
}

/*
 * Custom up/down sort icon view.
 */
public class GridSort : DXIcon
{
	/* Constants */
	private const double IconSize = 12;
	
	/* Methods */
	public GridSort( bool ascending )
	{
		Margin = 0;
		Size = IconSize;

		MaximumWidthRequest = IconSize;
		MaximumHeightRequest = IconSize;
		
		Resource = ascending ? "sort_up.png" : "sort_down.png";
		Color = DXColors.Dark1;

		Horizontal = LayoutOptions.Center;
		Vertical = LayoutOptions.Center;
		
		Aspect = Aspect.AspectFit;
	}
}

//
