using SVSim.BattleNode.Bridge;
using SVSim.BattleNode.Protocol;
namespace SVSim.BattleNode.Sessions;
///
/// One side of a battle. Two of these are held by a BattleSession; the session
/// brokers between them. Concrete impls:
///
/// - RealParticipant — WS-backed (used for BattleType.Pvp).
/// - NoOpBotParticipant — silent; for BattleType.Bot (AI-passive).
///
///
public interface IBattleParticipant : IAsyncDisposable
{
/// Real viewer id, or a synthetic stable id for bots
/// ().
long ViewerId { get; }
/// Per-battle MatchContext snapshot, used for building Matched/BattleStart
/// selfInfo when this participant is "self" in the perspective.
MatchContext Context { get; }
/// Session calls this to deliver a frame from the OTHER participant
/// (or a server-synthesized broadcast). Real impl: encode + WS-send.
/// NoOp: swallow.
/// True for control frames (BattleFinish, JudgeResult, ack);
/// bypasses playSeq assignment + archive.
Task PushAsync(MsgEnvelope envelope, bool noStock, CancellationToken ct);
/// Participant fires this when it has a frame to send TO the session
/// (its own gameplay action). Real impl: fires on WS recv. NoOp: never fires.
event Func? FrameEmitted;
/// Drives the participant's inbound loop. For Real: the WS read loop
/// (returns when the WS closes). For NoOp: completes immediately (the
/// session keeps running as long as the OTHER participant's RunAsync is alive).
Task RunAsync(CancellationToken ct);
/// Called when the battle ends. Concrete impls clean up (close WS, etc.).
Task TerminateAsync(BattleFinishReason reason);
}