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

using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;

using DXLib.UI;

using SizeF = Syncfusion.Drawing.SizeF;

namespace iStatVball3;

/*
 * Exports a Heat Map into a PDF document including both the heat map and report title.
 */
public class PDFHeat
{
	/* Fields */
	private HeatCard heatCard;

	// Calculated draw info
	private float netWd;
	private float courtSize;
	private float fullWd;

	private float courtX, courtX2;
	private float courtY;

	/* Methods */

	// Draws title and Heat Map to PDF page at specified location
	public async Task<float> Draw( PdfDocument document, HeatCard card, float y )
	{
		heatCard = card;

		float localY = y;

		// Use current page
		PdfPage page = document.Pages[ document.PageCount - 1 ];

		float wd = page.Graphics.ClientSize.Width;
		float ht = (wd * 0.50f);

		// Start new page if will not fit
		if ( (localY + ht) > page.Graphics.ClientSize.Height )
		{
			page = document.Pages.Add();

			localY = 0;
		}

		// Grid title
		localY = await PDFUtils.DrawText( page, card.Title, PDFUtils.BoldFont, 12, PDFUtils.GetColor( DXColors.Dark1 ), 0, localY );

		// Court
		localY = DrawCourt( page, (localY + PDFReport.TitleSpacing), wd, ht );

		// Map areas
		await DrawAreas( page );

		return localY;
	}

	// Draws court, net and lines (copied from HeatView)
	private float DrawCourt( PdfPage page, float y, float wd, float ht )
	{
		/* Layout Calculations */

		// Minimum out-of-bounds area
		float minOutWd = (ht * 0.130f);
		float minOutHt = (ht * 0.100f);

		// Proportional net size
		netWd = (ht * 0.030f);

		// Court size determined by minimum out-of-bounds
		float maxWd = (wd - (minOutWd * 2) - netWd) / 2;
		float maxHt = (ht - (minOutHt * 2));

		courtSize = Math.Min( maxWd, maxHt );
		fullWd = (courtSize + netWd + courtSize);

		// Courts always perfect square
		courtX = (wd - (courtSize * 2) - netWd) / 2;
		courtX2 = (courtX + courtSize + netWd);

		courtY = (y + ((ht - courtSize) / 2));
		float courtY2 = (courtY + courtSize);

		float netX = (courtX + courtSize);
		float netY = courtY;

		float antennaeSize = netWd;

		float frontrowWd = (courtSize / 3);
		float backrowWd = (frontrowWd * 2);

		// Line thickness proportional to court size
		float lineSize = (courtSize * 0.008f);

		// Colors
		PdfColor outerColor = PDFUtils.GetColor( HeatView.OuterColor );
		PdfColor innerColor = PDFUtils.GetColor( HeatView.InnerColor );

		PdfColor lineColor = PDFUtils.GetColor( HeatView.LineColor );
		PdfColor netColor = PDFUtils.GetColor( HeatView.NetColor );

		/* Drawing */

		// Fill outer court area
		PDFUtils.FillRectangle( page, outerColor, 0, y, wd, ht );

		// Fill inner court area
		PDFUtils.FillRectangle( page, innerColor, courtX, courtY, fullWd, courtSize );

		// Draw court lines
		PDFUtils.DrawRectangle( page, lineColor, lineSize, courtX, courtY, fullWd, courtSize );

		// Draw net (no shadow)
		PDFUtils.FillRectangle( page, netColor, netX, netY, netWd, courtSize );

		// Draw antennae (no shadow)
		PDFUtils.FillRectangle( page, netColor, netX, (courtY - antennaeSize), antennaeSize, antennaeSize );
		PDFUtils.FillRectangle( page, netColor, netX, courtY2, antennaeSize, antennaeSize );

		// Draw 10ft lines
		float lineX = (courtX + backrowWd);
		float lineX2 = (courtX2 + frontrowWd);

		PDFUtils.DrawLine( page, lineColor, lineSize, lineX, courtY, lineX, courtY2 );
		PDFUtils.DrawLine( page, lineColor, lineSize, lineX2, courtY, lineX2, courtY2 );

		return (y + ht);
	}

	// Draws all color-coded heat map areas (copied from HeatView)
	private async Task DrawAreas( PdfPage page )
	{
		// Config
		HeatMap map = heatCard.Map;
		HeatView view = heatCard.View;

		int areasX = heatCard.AreasX;
		int areasY = heatCard.AreasY;

		float[] results = map.Results;
		RecordCourt.Side side = map.Side;

		const float outlineWd = HeatView.OutlineWd;

		// Colors
		PdfColor outlineColor = PDFUtils.GetColor( HeatView.OutlineColor );
		PdfColor textColor = PDFUtils.GetColor( HeatView.TextColor );

		// Dimensions of each area
		float wd = (courtSize / areasX);
		float ht = (courtSize / areasY);

		// Font size based on smaller dimension
		float fontSize = (Math.Min( wd, ht ) / 4);

		bool sideA = (side == RecordCourt.Side.SideA);

		// Drawing court side A or B?
		float startX = sideA ? courtX : courtX2;

		// Traverse grid
		for ( int areaY = 0; areaY < areasY; areaY++ )
		{
			for ( int areaX = 0; areaX < areasX; areaX++ )
			{
				// Index into map
				int index = (areaY * areasX) + areaX;

				// Determine color for result value
				float result = results[ index ];
				PdfColor color = PDFUtils.GetColor( view.GetColor( result ) );

				float x = startX + (areaX * wd);
				float y = courtY + (areaY * ht);

				// Fill area
				PDFUtils.FillRectangle( page, color, x, y, (wd + 1), (ht + 1) );

				// Draw area outline
				PDFUtils.DrawRectangle( page, outlineColor, outlineWd, x, y, wd, ht );

				// String display is map type specific
				string format = view.GetFormat();

				// Result value
				string resultStr = double.IsNaN( result ) ? HeatView.EmptyResult : result.ToString( format );

				// Center text
				PdfFont font = await PDFUtils.GetFont( PDFUtils.NumberFont, fontSize);
				SizeF size = font.MeasureString( resultStr );

				float drawX = (x + ((wd - size.Width) / 2)) + outlineWd;
				float drawY = (y + ((ht - size.Height) / 2)) + outlineWd;

				// Draw
				await PDFUtils.DrawText( page, resultStr, PDFUtils.NumberFont, fontSize, textColor, drawX, drawY );
			}
		}
	}
}

//
