/* 
 * 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.Utils;
using DXLib.Video;

namespace iStatVball3;

/*
 * Implements a small data form for entering configuration options for match video sync. The form is displayed in a
 * modal popup.
 */
public class MatchVideoForm
{
	/* Constants */
	private static readonly Color DefaultColor = DXColors.Light4;

	/* Events */
	public Action<MatchVideo> Completed { get; set; }
	public Action Cancelled { get; set; }

	/* Properties */
	private bool IsRallySync => (recording == Match.RallySyncKey);
	
	/* Fields */

	// UI components
	private readonly DXVerticalLayout layout;
	private readonly DXButton okBtn;
	private readonly DXPopup popup;

	// Controls
	private DXFormControlList controls;

	// Underlying data
	private readonly MatchVideo video;
	private readonly string recording;

	/* Methods */
	public MatchVideoForm( MatchVideo video, string recording )
	{
		this.video = video;
		this.recording = recording;

		bool ios = DXDevice.IsIOS;
		
		// Controls are stacked
		layout = new DXVerticalLayout()
		{
			BackgroundColor = DefaultColor,

			Padding = 0,
			Spacing = 20,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Fill
		};

		// Controls
		CreateControls();

		// Button layout
		DXHorizontalLayout btnLayout = new()
		{
			BackgroundColor = DXColors.Light4,
			
			Padding = 0,
			Spacing = 10,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Start
		};
		
		// Cancel
		DXButton cancelBtn = new()
		{
			Resource = "alert.cancel",
			Type = DXButton.ButtonType.Neutral,
			ButtonWd = 75,

			ButtonTapped = OnCancelTapped
		};

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

			ButtonTapped = OnOkTapped
		};

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

		// Modal popup
		popup = new DXPopup( "video.title", layout )
		{
			IsModal = true,
			Padding = 0,
			
			ViewWidth = 375,
			ViewHeight = (ios ? 395 : 430),
		};
	}

	// Creates all form control fields
	private void CreateControls()
	{
		// Video setting fields
		controls = new DXFormControlList( false )
		{
			Padding = new Thickness( 24, 5, 24, 0 ),
			Color = DefaultColor,
			Title = null
		};

		bool hasData = (video != null);
		
		// Sync
		AddControl( new DXCheckboxField
		{
			Key = "sync",
			Text = "video.sync",
			Checked = hasData && video.Sync || IsRallySync,
			Help = "video.sync",

			ControlChanged = UpdateControls
		});

		// Host
		AddControl( new DXSelectorField
		{
			Key = "host",
			Title = "video.host",
			Items = "video.host",
			SelectedItem = hasData ? video.Host : null,
			Help = "video.host",

			ControlChanged = UpdateControls
		});

		// File ID
		AddControl( new DXVideoField
		{
			Key = "fileId",
			Title = "video.fileId",
			Text = hasData ? video.FileId : null,
			Host = hasData ? video.Host : null,

			ControlChanged = UpdateOk
		});

		// Sharing
		AddControl( new DXCheckboxField
		{
			Key = "share",
			Text = "video.share",
			Checked = hasData && video.Share,
			Help = "video.share"
		});

		// Init controls
		controls.Init();

		layout.Add( controls.View );

		// Set initial states
		UpdateControls();
	}

	// Adds control to list
	private void AddControl( DXFormControl control, bool required = true )
	{
  		controls.Add( control, required, false );
	}

	// Determines if any control has pending changes
	public bool HasChanges()
	{
		return controls.HasChanges();
	}

	// Determines if form has all valid values
	public bool IsValid()
	{
		bool sync = GetSync().Checked;
		
		bool hostValid = GetHost().HasSelection;
		bool idValid = GetFileId().IsValid();
		
		// Must have all fields defined
		return !sync || (hostValid && idValid);
	}
	
	// Shows video settings in modal popup
	public void Show( View view )
	{
		UpdateControls();

		popup.ShowFromView( view, 0, 20 );
	}

	/* Update */

	// Updates state of all controls
	private void UpdateControls()
	{
		bool sync = GetSync().Checked;

		GetSync().IsDisabled = IsRallySync;
		GetHost().IsDisabled = !sync;
		GetFileId().IsDisabled = !sync;
		GetShare().IsDisabled = !sync;

		// Host required
		bool hostErr = (sync && !GetHost().HasSelection);
		GetHost().SetState( hostErr ? DXFormControl.ControlState.Error : DXFormControl.ControlState.Normal );

		// File ID required
		bool idErr = (sync && !GetFileId().HasValue());
		GetFileId().SetState( idErr ? DXFormControl.ControlState.Error : DXFormControl.ControlState.Normal );
		
		// Update host specific ID validation
		GetFileId().Host = GetHost().SelectedItem;
		
		// Clear host/share if sync unchecked
		if ( !sync )
		{
			GetHost().SelectedItem = null;
			GetFileId().Text = null;
			GetShare().Checked = false;
		}
		
		UpdateOk();
	}

	// OK button only enabled if all controls valid
	private void UpdateOk()
	{
		okBtn?.IsDisabled = !IsValid();
	}

	/* Get */

	// Returns populated match video settings object
	private MatchVideo GetVideo()
	{
		return new MatchVideo
		{
			Sync = GetSync().Checked,
			Host = GetHost().SelectedItem,
			FileId = GetFileId().Text,
			Share = GetShare().Checked
		};
	}

	// Convenience methods for accessing individual controls
	private DXCheckboxField GetSync() { return controls.GetControl( "sync" ) as DXCheckboxField; }
	private DXSelectorField GetHost() { return controls.GetControl( "host" ) as DXSelectorField; }
	private DXVideoField GetFileId() { return controls.GetControl( "fileId" ) as DXVideoField; }
	private DXCheckboxField GetShare() { return controls.GetControl( "share" ) as DXCheckboxField; }

	/* Event Callbacks */

	// User tapped OK button
	private void OnOkTapped( object sender )
	{
		// Get current configuration
		MatchVideo newVideo = GetVideo();

		popup.Hide();

		// Callback listener
		Completed?.Invoke( newVideo );
	}
	
	// User cancelled modal popup
	private void OnCancelTapped( object sender )
	{
		popup.Hide();
		
		// Callback listener
		Cancelled?.Invoke();
	}
}

//
