using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using ProjectI.Builds;
using ProjectI.Combat;
using ProjectI.Runs;
using ProjectI.Sessions;
using ProjectI.Settings;
using UnityEngine;
using UnityEngine.UIElements;
using Cursor=UnityEngine.Cursor;
namespace ProjectI.UI
{
/// Local input/cursor owner only. Never pauses the host simulation or mutates installed upgrades.
public sealed class CoreInspectionPanel : IDisposable
{
private readonly VisualElement screen,panel,grid;
private readonly ScrollView statScroll,inventoryScroll,detailScroll;
private readonly Label empty,detailTitle,detailBody;
private readonly PrototypeSessionController session;
private readonly Func canRelock;
private readonly List<(Button Control,Func Value)> statRows=new List<(Button,Func)>();
private readonly Dictionary<(int,int),Button> tiles=new Dictionary<(int,int),Button>();
private readonly IVisualElementScheduledItem refreshTask,detailLayoutTask;
private VisualElement detailAnchor;
private Func detailText;
private bool detailHovered,anchorHovered;
private string inventoryIdentity;
private (int,int)? focusedUpgrade;
private BuildStats equippedBaseline;
public bool IsOpen=>!panel.ClassListContains("hidden");
public static bool CanOpen(bool connected,bool busy,bool menuVisible,bool settingsOpen,RunPhase phase)
=>connected&&!busy&&!menuVisible&&!settingsOpen&&(phase==RunPhase.Menu||phase==RunPhase.Active||phase==RunPhase.Collection);
public static Rect PlaceDetail(Rect viewport,Rect anchor,Vector2 requested)
{
float width=Mathf.Min(requested.x,Mathf.Max(0,viewport.width-16));
float height=Mathf.Min(requested.y,Mathf.Max(0,viewport.height-16));
float left=anchor.xMax+10;
if(left+width>viewport.xMax-8)left=anchor.xMin-width-10;
return new Rect(Mathf.Clamp(left,viewport.xMin+8,Mathf.Max(viewport.xMin+8,viewport.xMax-width-8)),
Mathf.Clamp(anchor.yMin,viewport.yMin+8,Mathf.Max(viewport.yMin+8,viewport.yMax-height-8)),width,height);
}
public static string Detail(UpgradeInventoryEntry entry,float maxHealth,float maxNormalShield)
{
var definition=UpgradeCatalog.Get(entry.UpgradeId);
if(definition==null)return "Unknown installed upgrade.";
var card=UpgradeCardFormatter.Format((UpgradeId)entry.UpgradeId,entry.Rank,new CoreDisplayContext(maxHealth,maxNormalShield),CorePresentationMode.Installed);
return card.Primary+(string.IsNullOrEmpty(card.Secondary)?"":"\n"+card.Secondary)+"\n\n"+card.Details;
}
public CoreInspectionPanel(VisualElement screen,PrototypeSessionController session,Func canRelock)
{
this.screen=screen;this.session=session;this.canRelock=canRelock;
panel=new VisualElement {name="coreInspectionPanel"};panel.AddToClassList("inspection-panel");panel.AddToClassList("hidden");
var header=new VisualElement();header.AddToClassList("inspection-header");panel.Add(header);
var title=new Label("RUN INSPECTION");title.AddToClassList("inspection-title");header.Add(title);
var close=new Button(()=>Close(true)){text="Close [Tab / Esc]",name="inspectionClose"};close.AddToClassList("inspection-close");header.Add(close);
var note=new Label("Run continues. Hover or focus a stat or core for its installed effect and sources.");note.AddToClassList("inspection-note");panel.Add(note);
var columns=new VisualElement();columns.AddToClassList("inspection-columns");panel.Add(columns);
statScroll=new ScrollView(ScrollViewMode.Vertical){name="inspectionStats"};statScroll.AddToClassList("inspection-stats");columns.Add(statScroll);
inventoryScroll=new ScrollView(ScrollViewMode.Vertical){name="inspectionInventory"};inventoryScroll.AddToClassList("inspection-inventory");columns.Add(inventoryScroll);
var installed=new Label("INSTALLED CORES");installed.AddToClassList("inspection-section");inventoryScroll.Add(installed);
var inventoryNote=new Label("Each tile is one installed core and ability recipient. Unspent cores remain on the combat HUD.");inventoryNote.AddToClassList("inspection-note");inventoryScroll.Add(inventoryNote);
empty=new Label("No cores installed yet. Collect cores, then choose after everyone enters the portal.");empty.AddToClassList("inspection-empty");inventoryScroll.Add(empty);
grid=new VisualElement {name="installedUpgradeGrid"};grid.AddToClassList("inspection-grid");inventoryScroll.Add(grid);
detailScroll=new ScrollView(ScrollViewMode.Vertical){name="inspectionDetail"};detailScroll.AddToClassList("inspection-detail");detailScroll.AddToClassList("hidden");
detailTitle=new Label();detailTitle.AddToClassList("inspection-detail-title");detailScroll.Add(detailTitle);
detailBody=new Label();detailBody.AddToClassList("inspection-detail-body");detailScroll.Add(detailBody);
detailScroll.RegisterCallback(_=>detailHovered=true);
detailScroll.RegisterCallback(_=>{detailHovered=false;ScheduleHideDetail();});
detailScroll.RegisterCallback(_=>ScheduleHideDetail());
screen.Add(panel);screen.Add(detailScroll);
refreshTask=panel.schedule.Execute(Refresh).Every(250);
detailLayoutTask=detailScroll.schedule.Execute(ResolveDetailLayout);
}
public bool Open()
{
var player=PrototypePlayerCombat.LocalPlayer;var run=PrototypeRunDirector.Instance;
if(player==null||!player.IsSpawned||session==null||!session.Connected||session.Busy||!canRelock()||LocalPlayerSettings.IsInputBlocked
||!CanOpen(true,false,false,false,run!=null?run.Phase:RunPhase.Menu))return false;
LocalPlayerSettings.SetInputBlocked(this,true);player.ClearHeldInputForInspection();
Cursor.lockState=CursorLockMode.None;Cursor.visible=true;
panel.RemoveFromClassList("hidden");panel.BringToFront();inventoryIdentity=null;
BuildStats(player);Refresh();panel.Q