using System;
using System.Diagnostics.CodeAnalysis;

namespace Rowa.Observables;

/// <summary>
/// A Subject that allows swapping its source, without removing active subscriptions
/// </summary>
/// <typeparam name="T"></typeparam>

public class SourceSubject<T> : IObservable<T>
{
    private readonly Subject<T> _internalSubject = new();
    private IDisposable? _externalSubscription;
    public IDisposable Subscribe(IObserver<T> observer)
    {
        return _internalSubject.Subscribe(observer);
    }

    [MaybeNull]
    public T Current
    {
        get => _internalSubject.Current;
        set => _internalSubject.Current = value;
    }


    public void SetSource(IObservable<T> source)
    {
        _externalSubscription?.Dispose();
        _externalSubscription = source.Subscribe(new DelegateObserver<T>(
            n => _internalSubject.Current = n, 
            () =>
            {
                _internalSubject.Complete();
                _externalSubscription?.Dispose();
                _externalSubscription = null;
            },
            ex => _internalSubject.SetError(ex)));
    }

}