using System;

internal class LazyLoader<T>
    where T : class, new()
{
    public bool IsCreated {
        get {
            return _isCreated;
        }
    }
    bool _isCreated = false;
    T _value = null;
    Func<T> creator;
    Action<T> destroyer;
    object creatorLock = new object();

    public static LazyLoader<T> Register(Func<T> creator, Action<T> destroyer = null)
    {
        var loader = new LazyLoader<T>();
        loader.creator = () => {
            var result = creator();
            loader._isCreated = true;
            return result;
        };
        loader.destroyer = (T instance) => {
            destroyer(instance);
            loader._isCreated = false;
        };
        return loader;
    }

    public void Destroy() {
        destroyer?.Invoke(Value);
        _value = null;
    }

    public T Value
    {
        get
        {
            if (!IsCreated) {
                lock(creatorLock) {
                    _value = IsCreated ? _value : creator();
                }
            }
            return _value;
        }
    }
}
