using System;
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Ui.Services;
namespace ClaudeDo.Ui.ViewModels.MissionControl;
///
/// Command Center pane hosting an embedded ConPTY terminal for either one task's interactive
/// Claude session, or an ad-hoc/free session in a user-chosen directory (no task,
/// is null — ad-hoc panes are never deduped, unlike task-based ones). Distinct from the streamed-log
/// pane; the two coexist until
/// the streaming interactive stack is removed.
///
public sealed partial class ConPtyPaneViewModel : ViewModelBase, IMissionControlPane, IDisposable
{
public string? TaskId { get; }
[ObservableProperty] private string _displayTitle;
public InteractiveTerminalViewModel Terminal { get; } = new();
/// Raised when the terminal failed to start — the host surfaces this via the footer error strip.
public event Action? ErrorReported;
/// Set by the host (Mission Control) to remove this pane from its collection.
public Action? CloseRequested { get; set; }
/// Task-based pane — dedup'd by . Pass null for an ad-hoc pane
/// (no task, never deduped); prefer at ad-hoc call sites.
public ConPtyPaneViewModel(string? taskId, string displayTitle, TerminalLaunchDescriptor descriptor)
{
TaskId = taskId;
_displayTitle = displayTitle;
Terminal.PropertyChanged += OnTerminalPropertyChanged;
Terminal.Start(descriptor);
}
/// Ad-hoc pane — no task, no dedup.
public static ConPtyPaneViewModel CreateAdHoc(string displayTitle, TerminalLaunchDescriptor descriptor)
=> new(null, displayTitle, descriptor);
private void OnTerminalPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(InteractiveTerminalViewModel.StartError) && Terminal.StartError is { Length: > 0 } error)
ErrorReported?.Invoke(error);
}
[RelayCommand]
private void Close() => CloseRequested?.Invoke(this);
public void Dispose()
{
Terminal.PropertyChanged -= OnTerminalPropertyChanged;
Terminal.Kill();
Terminal.Dispose();
}
}