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

using DXLib.UI;
using DXLib.UI.Layout;
using DXLib.UI.Container;
using DXLib.UI.Control.Button;

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

using DXLib.Data;

namespace iStatVball3;

/*
 * Implements the data form for creating/editing a custom report in the Report Builder control list. The data form is
 * displayed in a modal popup.
 */
public class CustomListForm
{
	/* Events */
	public Action<CustomReport,bool> Completed { get; set; }
	public Action Cancelled { get; set; }

	/* Properties */
	public CustomConfig Config { get; set; }

	/* Fields */
	private readonly DXGridLayout layout;
	private readonly DXFormControlList list;
	private readonly DXButton okBtn;

	private DXPopup popup;

	// External refs
	private readonly CustomControl customControl;
	private CustomReport customReport;

	// Edit or create mode?
	private readonly bool editing;

	/* Methods */
	public CustomListForm( CustomControl control, CustomReport report )
	{
		customControl = control;
		customReport = report;

		bool hasData = (report != null);

		// Edit or create?
		editing = hasData;

		// Layout
		layout = new DXGridLayout
		{
			BackgroundColor = DXColors.Light4,

			Padding = 0,
			RowSpacing = 10,
			ColumnSpacing = 0
		};

		// Control list
		list = new DXFormControlList( false )
		{
			Padding = new Thickness( 20, 10, 15, 20 )
		};

		// Category
		list.Add( new DXSelectorField
		{
			Key = "category",
			Title = "custom.category",
			Help = "custom.category",
			HideClear = true,

			ControlChanged = OnCategoryChanged
		},
		false, false );

		// Dimension
		list.Add( new DXSelectorField
		{
			IsVisible = hasData,

			Key = "dimension",
			Title = "custom.dimension",
			Help = "custom.dimension",
			HideClear = true,

			ControlChanged = Update
		},
		false, false );

		// Type
		list.Add( new DXSelectorField
		{
			IsVisible = hasData,

			Key = "type",
			Title = "custom.type",
			Help = "custom.type",
			HideClear = true,

			ControlChanged = OnTypeChanged
		},
		false, false );

		// Stat
		list.Add( new DXSelectorField
		{
			IsVisible = hasData,

			Key = "stat",
			Title = "custom.stat",
			Help = "custom.stat",
			HideClear = true,

			ControlChanged = OnStatChanged
		},
		false, false );

		// On dashboard card?
		list.Add( new DXCheckboxField
		{
			IsVisible = hasData,

			Key = "card",
			Text = "custom.card",
			Checked = false,
			Help = "custom.card",

			CheckboxToggled = Update
		},
		false, false );

		list.Init();

		// Button layout
		DXHorizontalLayout btnLayout = new()
		{
			BackgroundColor = DXColors.Light2,

			Padding = 0,
			Margin = 0,
			Spacing = 10,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};

		// Cancel
		DXButton cancelBtn = new()
		{
			Type = DXButton.ButtonType.Neutral,
			Resource = "alert.cancel",
			ButtonWd = 75,

			ButtonTapped = OnCancelTapped
		};

		cancelBtn.Init();
		
		// OK
		okBtn = new DXButton
		{
			Type = DXButton.ButtonType.Positive,
			Resource = "alert.ok",

			ButtonTapped = OnOkTapped
		};

		okBtn.Init();
		
		btnLayout.Add( cancelBtn );
		btnLayout.Add( okBtn );

		// 2 rows
		layout.AddStarRow();            // 0: list
		layout.AddFixedRow( 60 );       // 1: buttons

		layout.Fill( DXPopup.DefaultHeaderColor, 0, 1 );

		// Add components
		layout.Add( list.View, 0, 0 );
		layout.Add( btnLayout, 0, 1 );
	}

	// Post construction initialization
	public void Init()
	{
		List<DXItem> categories = DashboardCache.Instance.GetCategoryList( Config.IsTeam1 );

		// Populate categories
		Category.ItemList = categories;
		Category.SelectedItem = customReport?.Category;

		// Populate all other fields
		Populate( customReport );

		Update();
	}

	// Populates all data fields from existing custom report
	private void Populate( CustomReport report )
	{
		if ( report != null )
		{
			DashboardCache cache = DashboardCache.Instance;

			bool team1 = Config.IsTeam1;

			string category = report.Category;
			string dimension = report.Dimension;
			string type = report.Type;
			string stat = report.Stat;

			// Retrieve item lists applicable for specified report
			List<DXItem> categories = cache.GetCategoryList( team1 );
			List<DXItem> dimensions = DashboardCache.GetDimensionList( category, team1 );
			List<DXItem> types = DashboardCache.GetTypeList( category );
			List<DXItem> stats = cache.GetStatList( category, type );

			// Populate selectors
			Category.ItemList = categories;
			Dimension.ItemList = dimensions;
			Type.ItemList = types;
			Stat.ItemList = stats;

			// Set current selections
			Category.SelectedItem = category;
			Dimension.SelectedItem = dimension;
			Type.SelectedItem = type;
			Stat.SelectedItem = stat;

			Card.Checked = report.IsOnCard;
		}
	}

	// Displays modal Report Builder popup
	public void Show()
	{
		// Display modal
		popup = new DXPopup()
		{
			IsModal = true,
			ViewWidth = 340,
			AutoSize = true,
		};

		popup.SetTitle( Config.Name );
		popup.SetContent( layout );

		popup.Show();
	}

	// Dismisses modal popup
	private void Hide()
	{
		popup.Hide();
	}

	// Determines if form valid (all fields selected)
	public bool IsValid()
	{
		return Category.HasValue() &&
			   (Dimension.IsDisabled || Dimension.HasValue()) &&
			   Type.HasValue() &&
			   Stat.HasValue();
	}

	// Populates custom report data model from form fields
	private void Save()
	{
		// Create new report
		customReport ??= new CustomReport();

		// Save all fields
		customReport.Category = Category.GetObject() as string;
		customReport.Dimension = Dimension.GetObject() as string;
		customReport.Type = Type.GetObject() as string;
		customReport.Stat = Stat.GetObject() as string;
		customReport.IsOnCard = (bool) Card.GetObject();
	}

	// Updates OK button and 'Show on dashboard card?' states
	private void Update()
	{
		// OK only enabled if all required fields populated
		okBtn.IsDisabled = !IsValid();

		bool hasStat = Stat.HasValue();

		// Stat must be selected before checkbox visible
		Card.IsVisible = hasStat;

		// Checkbox disabled in some states
		if ( hasStat )
		{
			JsonReport jsonReport = DashboardCache.Instance.GetReport( CategoryKey, TypeKey, StatKey );
			JsonCustom jsonCustom = jsonReport.Custom;

			// May already have max metrics (3)
			bool max = (customControl.GetCardCount() >= DashboardMetrics.MaxCount);
			bool full = max && customReport is not { IsOnCard: true };

			// NA for shot/heat
			bool invalid = TypeKey is AnalyzeKeys.ShotKey or AnalyzeKeys.HeatKey;

			Card.IsDisabled = jsonCustom is not { AllowCard: true } || full || invalid;
		}
	}

	/* Event Callbacks */

	// User saving report config
	private void OnOkTapped( object sender )
	{
		Save();

		// Callback listener
		Completed?.Invoke( customReport, editing );

		Hide();
	}

	// User dismissing modal popup
	private void OnCancelTapped( object sender )
	{
		Hide();

		// Callback listener
		Cancelled?.Invoke();
	}

	/* Dynamic Fields */

	// User chose new report category
	private void OnCategoryChanged()
	{
		Dimension.Clear();
		Type.Clear();
		Stat.Clear( true );

		Card.Checked = false;

		// Lookup available dimensions, types
		List<DXItem> dimensions = DashboardCache.GetDimensionList( CategoryKey, Config.IsTeam1 );
		List<DXItem> types = DashboardCache.GetTypeList( CategoryKey );

		Dimension.ItemList = dimensions;
		Type.ItemList = types;

		// Pre-select if only 1 item
		if ( dimensions.Count == 1 )
		{
			Dimension.SelectedItem = dimensions[0].Key;
		}
		// Might have none
		else if ( dimensions.Count == 0 )
        {
			Dimension.IsDisabled = true;
        }

		// Always at least one type
		if ( types.Count == 1 )
		{
			Type.SelectedItem = types[0].Key;
			OnTypeChanged();
		}

		Update();
	}

	// User chose new report type
	private void OnTypeChanged()
	{
		Stat.Clear();

		string category = Category.SelectedItem;
		string type = Type.SelectedItem;

		// Lookup available stats
		List<DXItem> stats = DashboardCache.Instance.GetStatList( category, type );

		Stat.ItemList = stats;

		// Pre-select if only 1 stat
		if ( stats.Count == 1 )
		{
			Stat.SelectedItem = stats[0].Key;
			OnStatChanged();
		}

		Update();
	}

	// User chose new stat, update UI
	private void OnStatChanged()
	{
		Update();
	}

	/* Control Accessors */

	private DXSelectorField Category => list.GetControl( "category" ) as DXSelectorField;
	private DXSelectorField Dimension => list.GetControl( "dimension" ) as DXSelectorField;
	private DXSelectorField Type => list.GetControl( "type" ) as DXSelectorField;
	private DXSelectorField Stat => list.GetControl( "stat" ) as DXSelectorField;

	private DXCheckboxField Card => list.GetControl( "card" ) as DXCheckboxField;

	private string CategoryKey => Category.SelectedItem;
	private string TypeKey => Type.SelectedItem;
	private string StatKey => Stat.SelectedItem;
}

//
