using System;
using System.Threading;

namespace QC.QSPR.Threading;

public class AbortableObject : DisposableObject
{
	private ManualResetEvent abortEvent = new ManualResetEvent(initialState: false);

	private ManualResetEvent abortCompleteEvent = new ManualResetEvent(initialState: false);

	private bool alreadyDisposed;

	public ManualResetEvent AbortEvent => abortEvent;

	public ManualResetEvent AbortCompleteEvent => abortCompleteEvent;

	public bool IsAbortSignaled => AbortEvent.WaitOne(0, exitContext: false);

	public bool IsAbortCompleteSignaled => AbortCompleteEvent.WaitOne(0, exitContext: false);

	public AbortableObject()
	{
		try
		{
			AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
			if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
			{
				AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
			}
		}
		catch
		{
		}
	}

	private void CurrentDomain_DomainUnload(object sender, EventArgs e)
	{
		Abort();
	}

	private void CurrentDomain_ProcessExit(object sender, EventArgs e)
	{
		Abort();
	}

	public virtual void Abort()
	{
		AbortEvent.Set();
	}

	public virtual void AbortAndWait(int millisecondsTimeout)
	{
		AbortEvent.Set();
		WaitHandle.WaitAny(new WaitHandle[2]
		{
			Shutdown.WaitHandle,
			AbortCompleteEvent
		}, millisecondsTimeout, exitContext: false);
	}

	public virtual void ResetAbort()
	{
		AbortCompleteEvent.Reset();
		AbortEvent.Reset();
	}

	protected override void Dispose(bool isDisposing)
	{
		if (!alreadyDisposed && isDisposing)
		{
			AppDomain.CurrentDomain.ProcessExit -= CurrentDomain_ProcessExit;
			if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
			{
				AppDomain.CurrentDomain.DomainUnload -= CurrentDomain_DomainUnload;
			}
			Abort();
			alreadyDisposed = true;
		}
		base.Dispose(isDisposing);
	}
}
