UI/DailyTrophyStandingsPanel.razor
@using Sandbox
@using Sandbox.UI
@using System
@using System.Linq
@inherits Panel
@namespace BlockParty
@attribute [StyleSheet( "MedalStandingsPanel.razor.scss" )]

<root class="daily-trophies @(Expanded ? "expanded" : "")">
	<PixelTooltip @ref="TooltipLayer"></PixelTooltip>
	@if ( Expanded )
	{
		<div class="shade" onclick=@Close></div>
	}
	@if ( !HasLetterbox && !Expanded )
	{
		<button class="compact-trigger" onclick=@Open>TROPHIES</button>
	}
	else
	{
		<div class="@(Expanded ? "standings-content" : "standings-rail")" style=@CardStyle>
			<div class="medal-card trophy-card">
				<div class="heading">
					<label class="title">@(Expanded ? "TROPHIES" : "TROPHIES")</label>
					@if ( Expanded )
					{
						<button class="square-btn i-close close" onclick=@Close><div class="img"></div></button>
					}
				</div>
				@if ( Current is null )
				{
					<label class="notice">@(DailyTrophyStandings.Notice ?? "Loading trophies...")</label>
				}
				else if ( Current.Players.Count == 0 )
				{
					<label class="notice empty-medals">No trophies earned yet.</label>
				}
				else
				{
					<div class="columns">
						<div class="column-spacer"></div>
						<div class="medal"><TrophyIcon Place=@(1) OnHover=@Tip( AwardPoints.Tip( 1 ) ) Size=@(Expanded ? 44 : 32)></TrophyIcon></div>
						<div class="medal"><TrophyIcon Place=@(2) OnHover=@Tip( AwardPoints.Tip( 2 ) ) Size=@(Expanded ? 44 : 32)></TrophyIcon></div>
						<div class="medal"><TrophyIcon Place=@(3) OnHover=@Tip( AwardPoints.Tip( 3 ) ) Size=@(Expanded ? 44 : 32)></TrophyIcon></div>
						@if ( Expanded ) { <div class="points"></div> }
					</div>
					<div class="medal-list">
						@foreach ( var player in Current.Players.Take( Expanded ? Current.Players.Count : 5 ) )
						{
							<div class="medal-row @(player.AccountId == (long)Game.SteamId ? "you" : "")">
								<label class="rank">@player.Rank</label>
								<SteamAvatar [email protected] Size=@(Expanded ? 36 : 28)></SteamAvatar>
								<LiteralLabel class="name" [email protected] />
								<label class="medal gold @(player.Gold == 0 ? "zero" : "")">@player.Gold</label>
								<label class="medal silver @(player.Silver == 0 ? "zero" : "")">@player.Silver</label>
								<label class="medal bronze @(player.Bronze == 0 ? "zero" : "")">@player.Bronze</label>
								@if ( Expanded ) { <label class="points" onmouseover=@Tip( "Total points" )>@player.Points</label> }
							</div>
						}
					</div>
					@if ( !Expanded && Current.Players.Skip( 5 ).FirstOrDefault( player => player.AccountId == (long)Game.SteamId ) is DailyTrophyPlayer me )
					{
						<div class="medal-row you personal">
							<label class="rank">@me.Rank</label><label class="name">YOU</label>
							<label class="medal gold @(me.Gold == 0 ? "zero" : "")">@me.Gold</label>
							<label class="medal silver @(me.Silver == 0 ? "zero" : "")">@me.Silver</label>
							<label class="medal bronze @(me.Bronze == 0 ? "zero" : "")">@me.Bronze</label>
						</div>
					}
				}
				@if ( Expanded && Current is not null )
				{
					<label class="freshness">@Freshness</label>
					<label class="freshness">Latest day: @DailyChallenge.DisplayDate( Current.ThroughDay )</label>
					@if ( DailyTrophyStandings.Notice is string notice )
					{
						<label class="freshness">@notice</label>
					}
				}
				@if ( Current?.DaysPending > 0 )
				{
					<label class="freshness">@Current.DaysPending @(Current.DaysPending == 1 ? "day" : "days") pending</label>
				}
				@if ( !Expanded )
				{
					<button class="view-all" onclick=@Open>VIEW MORE</button>
				}
			</div>
		</div>
	}
</root>

@code
{
	// Keep the tooltip outside the scrolling rows so it cannot be clipped.
	private PixelTooltip TooltipLayer { get; set; }
	private Panel _tipPanel;
	private string _tipText;
	private Action<PanelEvent> Tip( string text ) => e => { _tipPanel = e.This; _tipText = text; };
	private void UpdateTooltip()
	{
		if ( _tipPanel.IsValid() && _tipPanel.HasHovered ) TooltipLayer?.Show( _tipText );
		else TooltipLayer?.Hide();
	}

	public bool Expanded { get; private set; }
	private DailyTrophySnapshot Current => DailyTrophyStandings.Current;
	public override void OnMouseWheel( Vector2 value ) { }
	private float ViewWidth => 1080f * Screen.Width / Math.Max( 1f, Screen.Height );
	private float LetterboxWidth => (ViewWidth - 1080f) * 0.5f;
	private bool HasLetterbox => LetterboxWidth >= 320f;
	private double AgeMinutes => Current is null ? 0 : Math.Max( 0, (DateTimeOffset.UtcNow - Current.UpdatedAt).TotalMinutes );
	private string Freshness => $"Updated {(AgeMinutes < 1 ? "just now" : AgeMinutes < 60 ? $"{(int)AgeMinutes}m ago" : $"{(int)(AgeMinutes / 60)}h ago")}";
	private string CardStyle => Expanded
		? $"width:{Px( Math.Min( 820f, ViewWidth - 64f ) )};"
		: $"width:{Px( Math.Min( 360f, LetterboxWidth - 40f ) )};right:{Px( (LetterboxWidth - Math.Min( 360f, LetterboxWidth - 40f )) * 0.5f )};";
	private static string Px( float value ) => value.ToString( "0.###", System.Globalization.CultureInfo.InvariantCulture ) + "px";
	private void Open() { Expanded = true; StateHasChanged(); }
	public void Close() { Expanded = false; StateHasChanged(); }
	public override void Tick() { UpdateTooltip(); DailyTrophyStandings.Tick(); }
	protected override int BuildHash() => HashCode.Combine( Expanded, DailyTrophyStandings.Revision, (int)ViewWidth, (int)AgeMinutes );
}