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

using System.Collections.ObjectModel;
using Syncfusion.Maui.Charts;

using DXLib.UI;
using DXLib.UI.Container;

using DXLib.Utils;

namespace iStatVball3;

/*
 * Renders a Momentum Chart line graph using the SfCartesianChart library. Score is on the X axis and Momentum on the Y axis.
 */
public class MomentumView : DXContent
{
	/* Constants */

	// Y-axis +/- range
	private const int MaxRange = 20;

	/* Properties */

	// External access required for PDF export
	public SfCartesianChart Chart { get; private set; }

	/* Fields */
	private LineSeries series;

	// Axes
	private CategoryAxis primaryAxis;
	private NumericalAxis secondaryAxis;

	/* Methods */

	// Post construction initialization
	public void Init()
	{
		Horizontal = LayoutOptions.Fill;
		Vertical = LayoutOptions.Fill;
		
		BackgroundColor = DXColors.Light4;

		// Momentum Chart
		Chart = new SfCartesianChart
		{
			IsTransposed = false,
			
			// No title
			Title = null!
		};

		// X,Y axes
		primaryAxis = InitPrimary();
		secondaryAxis = InitSecondary();

		Chart.XAxes.Add( primaryAxis );
		Chart.YAxes.Add( secondaryAxis );

		// X axis line crosses at 0
		InitAxisLine();
		
		// Single line color
		List<Brush> brushes = [ new SolidColorBrush( DXColors.Action ) ];
		
		// No selections
		DataPointSelectionBehavior selection = new()
		{
			Type = ChartSelectionType.None
		};

		// Data series
		series = new LineSeries
		{
			IsVisible = true,

			XBindingPath = "Score",
			YBindingPath = "Momentum",

			// Line
			Opacity = 1.0,
			StrokeWidth = 3,

			// Custom palette
			PaletteBrushes = brushes,
			
			// Animation
			EnableAnimation = true,

			// No selection
			SelectionBehavior = selection,
			EnableTooltip = false
		};

		Chart.Series.Add( series );

		// // Register for events
		// Chart.AnnotationClicked += OnDotTapped;

		Content = Chart;
	}

	// Loads data series into line chart
	public void LoadData( List<MomentumDatum> data )
	{
		series.ItemsSource = new ObservableCollection<MomentumDatum>( data );
	}

	// Adds annotation onto line chart
	public void AddAnnotation( ChartAnnotation annotation )
	{
		Chart.Annotations.Add( annotation );
	}

	// Initializes Momentum Chart x-axis (primary)
	private static CategoryAxis InitPrimary()
	{
		// Title
		ChartAxisTitle title = new()
		{
			Text = DXString.Get( "momentum.title.x" ),
			TextColor = DXColors.Dark1,

			Background = DXColors.Transparent,
			StrokeWidth = 0,
			Margin = 0,

			FontFamily = DXFonts.Roboto,
			FontAttributes = FontAttributes.Bold,
			FontSize = 14
		};

		// Axis line
		ChartLineStyle lineStyle = new()
		{
			Stroke = DXColors.Dark1,
			StrokeWidth = 2
		};

		// Tick labels
		ChartAxisLabelStyle labelStyle = new()
		{
			TextColor = DXColors.Dark1,

			LabelAlignment = ChartAxisLabelAlignment.Center,
			WrappedLabelAlignment = ChartAxisLabelAlignment.Center,

			Background = DXColors.Transparent,
			StrokeWidth = 0,
			Margin = 4,

			FontFamily = DXFonts.Roboto,
			FontAttributes = FontAttributes.None,
			FontSize = 10
		};

		// Tick marks
		ChartAxisTickStyle tickStyle = new()
		{
			TickSize = 7,
			Stroke = DXColors.Dark1,
			StrokeWidth = 1
		};

		// Grid lines
		ChartLineStyle gridStyle = new()
		{
			Stroke = DXColors.Light1,
			StrokeWidth = 1
		};

		// X axis
		CategoryAxis axis = new()
		{
			Title = title,

			IsVisible = true,
			IsInversed = false,

			// Axis between -20, 20
			EdgeLabelsDrawingMode = EdgeLabelsDrawingMode.Center,
			AxisLineStyle = lineStyle,

			// Score label at every tick
			Interval = 1,
			TickPosition = AxisElementPosition.Outside,
			MajorTickStyle = tickStyle,

			// Tick labels
			LabelPlacement = LabelPlacement.OnTicks,
			LabelsIntersectAction = AxisLabelsIntersectAction.None,
			LabelRotation = 0,
			LabelExtent = 8,
			LabelStyle = labelStyle,

			// No end range margin
			PlotOffsetStart = 0,
			PlotOffsetEnd = 0,
			AxisLineOffset = 0,

			// Grid lines
			ShowMajorGridLines = true,
			MajorGridLineStyle = gridStyle
		};

		return axis;
	}

	// Initializes Momentum Chart y-axis (secondary)
	private static NumericalAxis InitSecondary()
	{
		// Title
		ChartAxisTitle title = new()
		{
			Text = DXString.Get( "momentum.title.y" ),
			TextColor = DXColors.Dark1,

			Background = DXColors.Transparent,
			StrokeWidth = 0,
			Margin = 0,

			FontFamily = DXFonts.Roboto,
			FontAttributes = FontAttributes.Bold,
			FontSize = 14
		};

		// Axis line
		ChartLineStyle lineStyle = new()
		{
			Stroke = DXColors.Dark1,
			StrokeWidth = 2
		};

		// Tick labels
		ChartAxisLabelStyle labelStyle = new()
		{
			TextColor = DXColors.Dark1,
			LabelAlignment = ChartAxisLabelAlignment.Center,

			Background = DXColors.Transparent,
			StrokeWidth = 0,
			Margin = 4,

			FontFamily = DXFonts.Roboto,
			FontAttributes = FontAttributes.None,
			FontSize = 10
		};

		// Major/minor tick marks
		ChartAxisTickStyle majorTickStyle = new()
		{
			TickSize = 7,
			Stroke = DXColors.Dark1,
			StrokeWidth = 1
		};

		ChartAxisTickStyle minorTickStyle = new()
		{
			TickSize = 4,
			Stroke = DXColors.Dark1,
			StrokeWidth = 1
		};

		// Grid lines
		ChartLineStyle gridStyle = new()
		{
			Stroke = DXColors.Light1,
			StrokeWidth = 1
		};

		// Y axis
		NumericalAxis axis = new()
		{
			Title = title,

			// Fixed range
			Minimum = -MaxRange,
			Maximum = MaxRange,

			IsVisible = true,
			IsInversed = false,

			EdgeLabelsDrawingMode = EdgeLabelsDrawingMode.Center,
			EdgeLabelsVisibilityMode = EdgeLabelsVisibilityMode.AlwaysVisible,

			// Labels every other tick
			Interval = 2,
			MinorTicksPerInterval = 1,
			TickPosition = AxisElementPosition.Outside,

			MajorTickStyle = majorTickStyle,
			MinorTickStyle = minorTickStyle,

			// Tick labels
			LabelsIntersectAction = AxisLabelsIntersectAction.None,
			LabelStyle = labelStyle,
			LabelRotation = 0,
			LabelExtent = 8,

			// No end range margin
			PlotOffsetStart = 0,
			PlotOffsetEnd = 0,
			AxisLineOffset = 0,
			AxisLineStyle = lineStyle,

			// Grid lines
			ShowMajorGridLines = true,
			ShowMinorGridLines = true,

			MajorGridLineStyle = gridStyle,
			MinorGridLineStyle = gridStyle
		};

		// Positive/Negative coloring
		AddShading( axis );

		return axis;
	}

	// Shades positive/negative graph ranges
	private static void AddShading( NumericalAxis axis )
	{
		NumericalPlotBandCollection bandCollection = [];
		
		// Translucent green positive range
		NumericalPlotBand positiveBand = new()
		{
			IsVisible = true,
			Start = 0,

			Fill = DXColors.Positive.WithAlpha( 0.10f ),
			StrokeWidth = 0
		};

		bandCollection.Add( positiveBand );
		
		// Translucent red negative range
		NumericalPlotBand negativeBand = new()
		{
			IsVisible = true,
			Start = -MaxRange,
			End = 0,

			Fill = DXColors.Negative.WithAlpha( 0.10f ),
			StrokeWidth = 0
		};

		bandCollection.Add( negativeBand );

		axis.PlotBands = bandCollection;
	}

	// Draws X axis line at Y0
	private void InitAxisLine()
	{
		HorizontalLineAnnotation axisLine = new()
		{
			IsVisible = true,
			CoordinateUnit = ChartCoordinateUnit.Axis,

			X1 = 0,
			Y1 = 0,

			// No labels
			LineCap = ChartLineCap.None,
			ShowAxisLabel = false,

			// Thickness
			Stroke = DXColors.Dark1,
			StrokeWidth = 2
		};

		Chart.Annotations.Add( axisLine );
	}

	/* Event Callbacks */

	// // User tapped an annotation dot
	// private void OnDotTapped( object sender, AnnotationClickedEventArgs args )
	// {
	// 	MomentumDot dot = args.Annotation as MomentumDot;
	//
	// 	// Calc dot location
	// 	double x = (ReportLayout.BasePadding + args.X);		// Do NOT include bounds here
	// 	double y = (Builder.GetViewHt() + Bounds.Y + args.Y);
	//
	// 	// Show in non-modal popup
	// 	MomentumDot.ShowPopup( dot, x, y );
	// }

	/* Layout */

	// Defines platform/orientation specific layout sizing
	public override void UpdateLayout( LayoutType type )
	{
		base.UpdateLayout( type );
		
		double wd = DXDevice.GetScreenWd();
		double ht = DXDevice.GetScreenHt();

		double padWd = (ReportLayout.BasePadding * 2) + Margin.HorizontalThickness;
		const double stripeWd = ReportCard.StripeWd;

		// Dynamically size based on orientation
		if ( DXDevice.IsMobile )
		{
			WidthRequest = (type == LayoutType.MobilePortrait) ? (wd * 1.75) : (wd - DXDevice.SafeArea().Left - padWd - stripeWd);
			HeightRequest = (type == LayoutType.MobileLandscape) ? 462 : 375;
		}
		else
		{
			WidthRequest = (wd - padWd - stripeWd);
			HeightRequest = ht * ((type == LayoutType.Landscape) ? 0.615 : 0.366);
		}
	}
}

//
