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

using DXLib.UI.Control;
using DXLib.UI.Control.Image;
using DXLib.UI.Control.Button;

using DXLib.Billing;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Implements In-App Purchase interface for purchasing additional consumable Team-Seasons. The interface is displayed in
 * a modal popup. Current product prices are queried from the AppStore.
 */
public class PurchaseView : DXPopup
{
	/* Constants */
	private static readonly double Pad = DXDevice.IsTablet ? 24 : 15;

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

	/* Fields */
	private readonly DXScroll scroll;
	private readonly DXGridLayout layout;
	private readonly List<DXRadioButton> productBtns;

	private DXButton purchaseBtn;

	/* Methods */
	public PurchaseView()
	{
		bool tablet = DXDevice.IsTablet;

		IsModal = true;

		// Mobile landscape needs to scroll
		scroll = new DXScroll
		{
			Orientation = ScrollOrientation.Vertical,
			Padding = 0,
			BackgroundColor = DXColors.Dark2
		};

		// Content layout
		layout = new DXGridLayout
		{
			Padding = new Thickness( 0, 0, 0, 10 ),
			RowSpacing = tablet ? 20 : 19,
			ColumnSpacing = 0,

			BackgroundColor = DXColors.Light4,

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

		scroll.Content = layout;

		// Fixed size
		ViewWidth = tablet ? 500 : 440;
		ViewHeight = tablet ? 450 : 460;

		// Allocate container
		productBtns = [];
	}

	// Displays product list and purchase options in modal popup
	public async Task ShowProducts()
	{
		DXSpinner.Start();

		// Query products/prices
		List<DXBillingProduct> products = await PurchaseEngine.GetProducts();

		//// Create test products
		//products.Add( CreateProduct( "1 Team-Season", "39.99", "01" ) );
		//products.Add( CreateProduct( "5 Team-Seasons", "179.99", "05" ) );
		//products.Add( CreateProduct( "10 Team-Seasons", "299.99", "10" ) );
		//products.Add( CreateProduct( "20 Team-Seasons", "399.99", "20" ) );

		if ( products != null )
		{
			// Header
			AddImage();

			// Product rows
			foreach ( DXBillingProduct product in products )
			{
				AddProductRow( product, products );
			}

			// Fine print
			AddDetail();

			// Cancel/Purchase
			AddButtons();

			// Show fullscreen
			SetContent( scroll );
			Show( false );

			DXSpinner.Stop();
		}
		// Error
		else
		{
			DXAlert.ShowError( "purchase.title", "purchase.err.product" );

			Cancelled?.Invoke();
		}
	}

	//// Used internally to create products for testing only
	//DXBillingProduct CreateProduct( string name, string price, string idSuffix )
	//{
	//	return new DXBillingProduct
	//	{
	//		Name = name,
	//		LocalizedPrice = $"${price}",
	//		ProductId = $"istatvball3_teamseason_{idSuffix}"
	//	};
	//}

	/* Add */

	// Adds 'iStatVball 3' header image
	private void AddImage()
	{
		DXImage logoImg = new()
		{
			DownsampleToViewSize = false,
			
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};

		logoImg.FromResource( "logo_purchase.png" );
		logoImg.SetSize( 317, 36 );
		
		layout.AddFixedRow( 80 );
		layout.Fill( DXColors.Dark2, 0, 0 );
		layout.Add( logoImg, 0, 0 );
	}

	// Adds individual product row with select, name, price, and discount
	private void AddProductRow( DXBillingProduct product, List<DXBillingProduct> products )
	{
		bool tablet = DXDevice.IsTablet;

		// Inner layout
		DXGridLayout rowLayout = new()
		{
			Padding = new Thickness( Pad, 0 ),
			ColumnSpacing = tablet ? 15 : 10,
			RowSpacing = 0,

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

		// Select
		DXRadioButton selectBtn = new()
		{
			Key = product.ProductId,
			
			OnColor = DXColors.Positive,
			OffColor = DXColors.Dark3,
			
			Padding = 0,
			Margin = DXUtils.Top( -1 ),
			Size = 25,
		
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center,
		
			IsOn = (product.ProductId == Purchase.TeamSeasons1Id),
			TurnedOn = OnProductSelected
		};

		// Save in list for event handling
		productBtns.Add( selectBtn );

		rowLayout.AddFixedColumn( 30 );
		rowLayout.Add( selectBtn, 0, 0 );

		double fontSize = tablet ? 20 : 17;
		const double spacing = 10;

		// Name
		DXLabel nameLbl = new()
		{
			Text = product.Name,
			TextColor = DXColors.Dark1,

			Font = DXFonts.RobotoBold,
			FontSize = fontSize,

			HorizontalOptions = LayoutOptions.Start,
			VerticalOptions = LayoutOptions.Center					
		};

		rowLayout.AddStarColumn( 55 );
		rowLayout.Add( nameLbl, 1, 0 );

		// Price
		DXLabel priceLbl = new()
		{
			Text = product.LocalizedPrice,
			TextColor = DXColors.Dark1,

			Font = DXFonts.RobotoBold,
			FontSize = fontSize,

			HorizontalOptions = LayoutOptions.End,
			VerticalOptions = LayoutOptions.Center
		};

		rowLayout.AddStarColumn( 25 );
		rowLayout.Add( priceLbl, 2, 0 );

		rowLayout.AddStarColumn( 20 );

		// Determine % discount for product
		double discount = PurchaseEngine.DiscountForProduct( product.ProductId, products );

		// 'X% OFF'
		if ( discount > 0 )
		{
			string discountStr = $"{discount:N0}{DXString.Get( "purchase.discount" )}";

			DXLabel discountLbl = new()
			{
				Text = discountStr,
				TextColor = DXColors.Dark1,

				Font = DXFonts.Roboto,
				FontSize = tablet ? 17 : 14,

				HorizontalOptions = LayoutOptions.Center,
				VerticalOptions = LayoutOptions.Center
			};

			rowLayout.Add( discountLbl, 3, 0 );
		}

		layout.AddFixedRow( fontSize + spacing );
		layout.Add( rowLayout, 0, (layout.RowCount - 1) );
	}

	// Adds fine print verbiage below product list
	private void AddDetail()
	{
		// 'A Team-Season is...'
		DXLabel detail1 = new()
		{
			Margin = new Thickness( Pad, 0, Pad, 0 ),
			
			Resource = "purchase.detail1",
			TextColor = DXColors.Dark2,

			Font = DXFonts.Roboto,
			FontSize = 14,

			HAlign = TextAlignment.Center,
			LineBreakMode = LineBreakMode.WordWrap,

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

		layout.AddAutoRow();
		layout.Add( detail1, 0, (layout.RowCount - 1) );

		// 'considered used...'
		DXLabel detail2 = new()
		{
			Margin = new Thickness( Pad, -5, Pad, 0 ),
			
			Resource = "purchase.detail2",
			TextColor = DXColors.Dark3,

			Font = DXFonts.Roboto,
			FontSize = 12,

			HAlign = TextAlignment.Center,
			LineBreakMode = LineBreakMode.WordWrap,

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

		layout.AddAutoRow();
		layout.Add( detail2, 0, (layout.RowCount - 1) );
	}

	// Adds Cancel and Purchase buttons
	private void AddButtons()
	{
		// Inner layout
		DXHorizontalLayout buttonLayout = new()
		{
			Spacing = 8,
			Horizontal = LayoutOptions.Center
		};

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

			ButtonWd = 75,
			ButtonTapped = OnCancelTapped
		};

		cancelBtn.Init();

		// Purchase
		purchaseBtn = new DXButton
		{
			Resource = "purchase.title",
			Type = DXButton.ButtonType.Positive,

			IsSticky = true,

			ButtonWd = 95,
			ButtonTapped = OnPurchaseTapped
		};

		purchaseBtn.Init();
		
		buttonLayout.Add( cancelBtn );
		buttonLayout.Add( purchaseBtn );

		layout.AddFixedRow( 50 );
		layout.Add( buttonLayout, 0, (layout.RowCount - 1) );
	}

	/* Select */

	// Returns product ID for currently selected product
	private string GetSelected()
	{
		foreach ( DXRadioButton btn in productBtns )
		{
			if ( btn.IsOn )
			{
				return btn.Key;
			}
		}

		return null;
	}

	// Deselects all products except specified key
	private void DeselectAll( string key )
	{
		foreach ( DXRadioButton btn in productBtns )
		{
			if ( btn.Key != key )
			{
				btn.IsOn = false;
			}
		}
	}

	/* Event Callbacks */

	// User selected new product
	private void OnProductSelected( string key )
	{
		DeselectAll( key );
	}

	// User selected product and tapped purchase
	private async void OnPurchaseTapped( object sender )
	{
		DXSpinner.Start();

		string productId = GetSelected();

		// Start purchase flow (errors handled internally)
		DXBillingPurchase purchase = await DXBilling.Purchase( productId, DXBilling.ProductType.Consumable );

		// Success
		if ( purchase != null )
		{
			User user = Shell.CurrentUser;
			int count = Purchase.GetCount( productId );

			// Save purchase for current user
			await PurchaseEngine.Record( user, productId, purchase.PurchaseId, count );

			string msg = DXString.Get( ((count == 1) ? "purchase.success.1" : "purchase.success.N"), count );

			// Success!
			DXAlert.ShowOk( "purchase.success", "purchase.success.msg", msg, Completed );
		}
		// Error
		else
		{
			purchaseBtn.Reset();
		}

		DXSpinner.Stop();
	}

	// User tapped cancel button, callback listener
	private void OnCancelTapped( object sender )
	{
		Hide();

		Cancelled?.Invoke();
	}
}

//
