/* 
 * 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.Control;
using DXLib.UI.Layout;

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

using DXLib.Utils;

namespace iStatVball3;

/*
 * Custom form used only for lineup CRUD. The image area is replaced by the lineup control, which allows all entries of
 * a lineup for starters, subs, and swaps to be defined.
 */ 
public sealed class LineupForm : DXForm
{
	/* Properties */

	// Form fields changed via copy from?
	public bool HasCopyChanges { get; private set; }

	/* Fields */
	private readonly LineupControl lineupControl;

	// External reference
	private readonly Season season;

	// Copy from UI
	private DXFormControlList copyList;

	/* Methods */
	public LineupForm( Lineup lineup, Season season ) : base( lineup, "lineup", false, false, false )
	{
		this.season = season;

		header.Title = HasData ? lineup.Name : CreateHeader();

		// Required for permissions
		User user = Shell.CurrentUser;

		bool editable = !HasData || user.IsAdmin || !season.IsSample;

		// Roster
		List<Player> roster = season.GetActivePlayers();

		// Lineup control
		lineupControl = new LineupControl()
		{
			Roster = roster,
            IsEditEnabled = editable,
			Color = season.Color,

			Changed = OnLineupChanged
		};

        // Set initial data
        lineupControl.SetLineup( lineup );

		// Layout UI (default to Starters panel)
        lineupControl.Init();
		lineupControl.SelectStarters();

        /* Required */

        // Copy from
        AddCopyFrom();

        // Name
        AddControl( new DXTextField
		{
			Key = "name",
			Title = "form.name",
			Text = lineup?.Name,
			MinLength = 1,
			MaxLength = 64,
			Type = DXTextField.TextType.CapitalizeWords,
			Hint = DXFormControl.HintType.RequiredMin,
			Help = "lineup.name"
		}, true, true );

		/* Optional */

		// Description
		AddControl( new DXTextField
		{
			Key = "desc",
			Title = "form.desc",
			Text = lineup?.Description,
			MinLength = 1,
			MaxLength = 256,
			Help = "lineup.desc"
		}, false, false );

		// Notes
		AddControl( new DXEditorField
		{
			Key = "notes",
			Title = "form.notes",
			Text = lineup?.Notes,
			MaxLength = 1024,
			Help = "lineup.notes"
		}, false, false );

		// Control initialization
		Init();
    }

    // Include custom control in changes
    protected override bool HasChanges()
    {
        return (base.HasChanges() || HasCopyChanges || lineupControl.HasChanges());
    }

	/* CopyFrom */

	// Adds UI component for Copy From feature
    private void AddCopyFrom()
	{
		// Only valid for new lineup
        if ( !HasData )
        {
            if ( season.LineupList.Count > 0 )
            {
                // Copy from has own area
                copyList = new DXFormControlList( false )
                {
                    Color = DXColors.Accent1,
                    Title = DXString.Get( "lineup.copy" ),
                    IsReadOnly = false
                };

				// Copy from
                copyList.Add( new DXSelectorField
                {
                    Key = "copy",
                    Title = "lineup.singular",

                    Objects = season.LineupList,
                    SelectedObject = null,
                    IsDisabled = false,

                    Hint = DXFormControl.HintType.Required,
                    Help = "lineup.copy",

					ControlChanged = OnCopySelected
                }, false, false );

                copyList.Init();
            }
        }
    }

    /* Event Callbacks */

    // Copy From lineup selected
    private void OnCopySelected()
    {
        if ( copyList.GetControl( "copy" ) is DXSelectorField copy )
        {
            // Copy all form fields to new lineup
            if ( copy.GetObject() is Lineup lineup )
            {
	            if ( GetControl( "name", true ) is DXTextField name )
	            {
		            name.Text = lineup.Name;
	            }
	            if ( GetControl( "desc", false ) is DXTextField desc )
	            {
		            desc.Text = lineup.Description;   
	            }
                if ( GetControl( "notes", false ) is DXEditorField notes )
                {
	                notes.Text = lineup.Notes;
                }

                lineupControl.SetLineup( lineup );
                lineupControl.Update();

                bool permission = Shell.CurrentUser.IsAdmin || !IsReadOnly;

                // Save available now
                UpdateSave( permission );

				HasCopyChanges = true;
            }
        }
    }

    // Lineup control data changed
    private void OnLineupChanged()
	{
		bool permission = Shell.CurrentUser.IsAdmin || !IsReadOnly;

		UpdateSave( permission );
	}

    // User confirmed delete
    protected override async void OnDeleteConfirmed()
	{
		base.OnDeleteConfirmed();

		// Cascading delete
		if ( data is Lineup lineup )
		{
			await lineup.Delete();
		}

		// Refresh UI
		Shell.Instance.HideForm();
	}

	// Used confirmed cancel
	protected override void OnCancelConfirmed()
	{
		base.OnCancelConfirmed();

		Shell.Instance.HideForm();
	}

	// Used tapped save
	protected override async void OnSaveTapped()
	{
		// Validate
		if ( lineupControl.Validate() )
		{
			// Retrieve fields
			string name = GetString( "name", true );
			string desc = GetString( "desc", false );
			string notes = GetString( "notes", false );

            // Validate unique name
            if ( !HasData || (name != (data as Lineup)?.Name) )
            {
                if ( season.GetLineupByName( name ) != null )
                {
                    ShowUniqueError( "lineup", "season" );
                    return;
                }
            }

            base.OnSaveTapped();

            // Update existing object
            if ( HasData )
			{
				if ( data is Lineup lineup )
				{
					lineup.Name = name;
					lineup.Description = desc;
					lineup.Notes = notes;

					// Children
					lineup.Entries = lineupControl.Starters;
					lineup.Subs = lineupControl.Subs;
					lineup.Swaps = lineupControl.Swaps;

					// Persist
					await lineup.Update();
				}
			}
			// Create new object
			else
			{
				Lineup lineup = new()
				{
					Name = name,
					Description = desc,
					Notes = notes,

					// Children
					Entries = lineupControl.Starters,
					Subs = lineupControl.Subs,
					Swaps = lineupControl.Swaps,

					// Set parent
					SeasonId = season.UniqueId,
					Season = season
				};

				// Add to parent
				season.Lineups.Add( lineup );

				// Persist
				await lineup.Create();
			}

			// Refresh UI
			Shell.Instance.HideForm();
		}
	}
	
    /* Dynamic Fields */

    // Called back when any underlying control value changes
    protected override void OnControlChanged( object sender, DXFormChangedMessage msg )
    {
        base.OnControlChanged( sender, msg );

        if ( msg.Value is DXFormControl { Key: "copy" } )
        {
	        UpdateSave();
        }
    }

    /* Layout */

    // Redraws entire lineup form
    public override void UpdateLayout( LayoutType type )
	{
		base.UpdateLayout( type );

		// Update additional children
		lineupControl.UpdateLayout( type );
		
		DXSpinner.Stop();
	}

	// Landscape (4:3)
	protected override void Landscape()
	{
		// 3 rows
		Layout.AddFixedRow( 76 );          // 0: header
		Layout.AddStarRow();               // 1: builder, controls
		Layout.AddFixedRow( 68 );          // 2: builder, buttons

		// 2 columns
		Layout.AddStarColumn( 60 );        // 0: builder
		Layout.AddStarColumn( 40 );        // 1: controls, buttons

		// Header
		Layout.Add( header, 0, 0, 2, 1 );

		// Control
		Layout.Add( lineupControl, 0, 1, 1, 2 );

		// Form area (scrollable)
		if ( copyList != null )
		{
			LayoutP.Add( copyList.View );
		}

		LayoutP.Add( PrimaryList.View );
		LayoutP.Add( SecondaryList.View );

		// Entire grid scrolls
		scroll.BackgroundColor = DXColors.Light3;
		scroll.Content = LayoutP;

		Layout.Add( scroll, 1, 1 );

		// Buttons
		Layout.Add( buttons, 1, 2 );
	}

	// Portrait (3:4)
	protected override void Portrait()
	{
		bool ios = DXDevice.IsIOS;

		// Must recreate each time here
		DXGridLayout layoutP = new()
		{
			BackgroundColor = DXColors.Light4,

			RowSpacing = 0,
			ColumnSpacing = 0
		};

		bool hasCopy = (copyList != null);

		// 3 rows
		layoutP.AddStarRow( 70 );						// 0: builder
		layoutP.AddFixedRow( ios ? 68 : 53 );			// 1: header
		if ( hasCopy ) layoutP.AddFixedRow( 135 );		// 2: copy, secondary
		layoutP.AddStarRow( 30 );						// 3: primary, secondary

		// 2 columns
		layoutP.AddStarColumn();						// 0: primary
		layoutP.AddStarColumn();						// 1: secondary

		// Control
		layoutP.Add( lineupControl, 0, 0 );
		layoutP.SpanColumns( lineupControl, 2 );

		// Header
		layoutP.Add( header, 0, 1 );
		layoutP.SpanColumns( header, 2 );

        // Form area (scrollable)
        if ( hasCopy )
        {
            layoutP.Add( copyList.View, 0, 2 );
            layoutP.Add( PrimaryList.View, 0, 3 );
            layoutP.Add( SecondaryList.View, 1, 2, 1, 2 );
        }
		else
		{
            layoutP.Add( PrimaryList.View, 0, 2 );
            layoutP.Add( SecondaryList.View, 1, 2 );
        }

        // Entire grid scrolls
        scroll.Content = layoutP;

		Layout.AddStarRow();
		Layout.Add( scroll, 0, 0 );

		// Buttons
		Layout.AddFixedRow( 68 );
		Layout.Add( buttons, 0, 1 );
	}

	// Mobile Landscape
	protected override void MobileLandscape()
	{
		double dim = DXDevice.GetScreenDim();

		// Lineup control dynamically sized
		lineupControl.HeightRequest = (dim * 0.50);

		// Must recreate each time here
		DXGridLayout layoutL = new()
		{
			BackgroundColor = DXColors.Light4,

			RowSpacing = 0,
			ColumnSpacing = 0,
			
			Horizontal = LayoutOptions.Fill,
			Vertical = LayoutOptions.Fill,
			
			// REQUIRED
			IgnoreSafeArea = true
		};

		bool hasCopy = (copyList != null);

		// 3 inner rows
		layoutL.AddFixedRow( 50 );				// 0: header
		if ( hasCopy ) layoutL.AddAutoRow();
		layoutL.AddAutoRow();					// 1: builder, primary
		layoutL.AddStarRow();					// 2: builder, secondary

		// 2 columns
		layoutL.AddStarColumn( 60 );			// 0: builder
		layoutL.AddStarColumn( 40 );			// 1: primary, secondary

		// Add views
		layoutL.Add( header, 1, 0 );
		layoutL.Add( lineupControl, 0, 0 );

		if ( hasCopy )
		{
            layoutL.SpanRows( lineupControl, 4 );

            layoutL.Add( copyList.View, 1, 1 );
            layoutL.Add( PrimaryList.View, 1, 2 );
            layoutL.Add( SecondaryList.View, 1, 3 );
		}
		else
		{
            layoutL.SpanRows( lineupControl, 3 );

            layoutL.Add( PrimaryList.View, 1, 1 );
            layoutL.Add( SecondaryList.View, 1, 2 );
        }

        // Entire grid scrolls
        scroll.Content = layoutL;

		Layout.AddStarRow();
		Layout.Add( scroll, 0, 0 );

		Layout.AddFixedRow( 52 );
		Layout.Add( buttons, 0, 1 );
	}

	// Mobile Portrait
	protected override void MobilePortrait()
	{
		double dim = DXDevice.GetScreenDim();

		// Lineup control dynamically sized
		lineupControl.HeightRequest = (dim * 0.50);

		// All views stacked vertically
		LayoutP.Add( lineupControl );
		LayoutP.Add( header );

		if ( copyList != null )
		{
			LayoutP.Add( copyList.View );
		}

		LayoutP.Add( PrimaryList.View );
		LayoutP.Add( SecondaryList.View );

		// Entire grid scrolls
		scroll.Content = LayoutP;

		Layout.AddStarRow();
		Layout.Add( scroll, 0, 0 );

		Layout.AddFixedRow( 52 );
		Layout.Add( buttons, 0, 1 );
	}
}

//
