using System.Windows.Input;
using ytLive.Helpers;
namespace ytLive.ViewModels;
/// Where the YouTube slot is in its own five-step flow.
public enum YouTubeSlotState
{
/// [ ▶ YouTube ]
Idle,
/// [ ▶ Live | 🔒 Private | ✕ ]
ChoosePrivacy,
/// [ ● Start Live | ✕ ] or [ ● Start Private | ✕ ]
Armed,
/// [ ■ Stop Live ] or [ ■ Stop Private ]
Streaming,
}
/// Where the Record slot is in its own three-step flow.
public enum RecordSlotState
{
/// [ ◉ Record ]
Idle,
/// [ ● Start Recording | ✕ ]
Armed,
/// [ ■ Stop Recording ]
Recording,
}
///
/// The top bar is THREE FIXED SLOTS (creator, 2026-11-13): Build Scenes, YouTube, Record. A slot never
/// changes the bar's shape — every state transition happens INSIDE its own slot, and the neighbouring
/// slots never move. Earlier attempts added completion states as siblings in the bar, which read as five
/// ungrouped toolbar items and pushed Record around.
///
public partial class MainViewModel
{
private YouTubeSlotState _youTubeStep = YouTubeSlotState.Idle;
private RecordSlotState _recordStep = RecordSlotState.Idle;
private bool _podcastLive; // true = Private chosen (the private-visibility test stream)
// ─── Build Scenes slot ───
// Enabled only while BOTH other slots are idle: editing a scene under a live stream or a running
// recording is what the lock is for, and the tooltip says so out loud.
public bool IsBuildScenesEnabled =>
_youTubeStep == YouTubeSlotState.Idle && _recordStep == RecordSlotState.Idle;
public string BuildScenesTooltip => IsBuildScenesEnabled
? "Edit layers, scenes and webcam placement"
: "Scene editing is locked while streaming or recording";
// ─── YouTube slot ───
public YouTubeSlotState YouTubeStep => _youTubeStep;
public bool IsYouTubeIdle => _youTubeStep == YouTubeSlotState.Idle;
public bool IsYouTubeChoosingPrivacy => _youTubeStep == YouTubeSlotState.ChoosePrivacy;
public bool IsYouTubeArmed => _youTubeStep == YouTubeSlotState.Armed;
public bool IsYouTubeStreaming => _youTubeStep == YouTubeSlotState.Streaming;
public bool IsLiveChosen => !_podcastLive;
public bool IsPrivateChosen => _podcastLive;
public string YouTubeArmLabel => _podcastLive ? "Start Private" : "Start Live";
public string YouTubeStopLabel => _podcastLive ? "Stop Private" : "Stop Live";
// ─── Record slot ───
public RecordSlotState RecordStep => _recordStep;
public bool IsRecordIdle => _recordStep == RecordSlotState.Idle;
public bool IsRecordArmed => _recordStep == RecordSlotState.Armed;
public bool IsRecordRecording => _recordStep == RecordSlotState.Recording;
public string RecordElapsedLabel => $"REC: {LiveElapsedText}";
public ICommand SelectBuildCommand { get; private set; } = null!;
public ICommand OpenYouTubeCommand { get; private set; } = null!;
public ICommand ChooseLiveCommand { get; private set; } = null!;
public ICommand ChoosePrivateCommand { get; private set; } = null!;
public ICommand CancelYouTubeCommand { get; private set; } = null!;
public ICommand StartYouTubeCommand { get; private set; } = null!;
public ICommand StopYouTubeCommand { get; private set; } = null!;
public ICommand OpenRecordCommand { get; private set; } = null!;
public ICommand StartRecordingCommand { get; private set; } = null!;
public ICommand CancelRecordCommand { get; private set; } = null!;
public ICommand StopRecordingCommand { get; private set; } = null!;
private void InitializeActivityCommands()
{
SelectBuildCommand = new RelayCommand(_ => RaiseSlotStates(), _ => IsBuildScenesEnabled);
OpenYouTubeCommand = new RelayCommand(_ => SetYouTubeStep(YouTubeSlotState.ChoosePrivacy));
ChooseLiveCommand = new RelayCommand(_ => { _podcastLive = false; SetYouTubeStep(YouTubeSlotState.Armed); });
ChoosePrivateCommand = new RelayCommand(_ => { _podcastLive = true; SetYouTubeStep(YouTubeSlotState.Armed); });
CancelYouTubeCommand = new RelayCommand(_ => SetYouTubeStep(YouTubeSlotState.Idle));
// Signed out still routes to sign-in rather than sitting dead (no-dead-ends rule).
StartYouTubeCommand = new RelayCommand(_ =>
{
if (!IsConnected) { _ = SignInAsync(); return; }
if (_podcastLive) BeginTestStream(); else StartSession();
SetYouTubeStep(YouTubeSlotState.Streaming);
});
StopYouTubeCommand = new RelayCommand(_ =>
{
StopStream();
SetYouTubeStep(YouTubeSlotState.Idle);
});
OpenRecordCommand = new RelayCommand(_ => SetRecordStep(RecordSlotState.Armed));
StartRecordingCommand = new RelayCommand(_ =>
{
BeginRecordOnly();
SetRecordStep(RecordSlotState.Recording);
});
CancelRecordCommand = new RelayCommand(_ => SetRecordStep(RecordSlotState.Idle));
StopRecordingCommand = new RelayCommand(_ =>
{
StopStream();
SetRecordStep(RecordSlotState.Idle);
});
}
private void SetYouTubeStep(YouTubeSlotState step)
{
_youTubeStep = step;
RaiseSlotStates();
}
private void SetRecordStep(RecordSlotState step)
{
_recordStep = step;
RaiseSlotStates();
}
/// One place that announces everything the three slots show, so no caller can forget a flag.
///
internal void RaiseSlotStates()
{
OnPropertyChanged(nameof(IsBuildScenesEnabled));
OnPropertyChanged(nameof(BuildScenesTooltip));
OnPropertyChanged(nameof(YouTubeStep));
OnPropertyChanged(nameof(IsYouTubeIdle));
OnPropertyChanged(nameof(IsYouTubeChoosingPrivacy));
OnPropertyChanged(nameof(IsYouTubeArmed));
OnPropertyChanged(nameof(IsYouTubeStreaming));
OnPropertyChanged(nameof(IsLiveChosen));
OnPropertyChanged(nameof(IsPrivateChosen));
OnPropertyChanged(nameof(YouTubeArmLabel));
OnPropertyChanged(nameof(YouTubeStopLabel));
OnPropertyChanged(nameof(RecordStep));
OnPropertyChanged(nameof(IsRecordIdle));
OnPropertyChanged(nameof(IsRecordArmed));
OnPropertyChanged(nameof(IsRecordRecording));
OnPropertyChanged(nameof(RecordElapsedLabel));
// Build Scenes is the edit surface, so the lock has to reach editing too.
EditingActive = IsBuildScenesEnabled;
}
}