// System
using System;
using System.Collections.Generic;
// Unity
using UnityEngine;
// GUPS - AntiCheat - Core
using GUPS.AntiCheat.Core.Monitor;
using GUPS.AntiCheat.Core.Watch;
namespace GUPS.AntiCheat.Monitor
{
///
/// An abstract base class that defines the common functionality for monitors in a Unity environment.
/// Implements the and interfaces.
///
///
///
/// The class serves as an abstract base for implementing monitors in Unity applications.
/// It provides methods to control the lifecycle of a monitoring process and supports the observer pattern
/// through the interface. Monitors can be started, paused, resumed, and stopped,
/// and they notify subscribed observers of relevant events during their lifecycle.
///
///
public abstract class AMonitor : MonoBehaviour, IMonitor, IWatchAble
{
// Name
#region Name
///
/// The name of the monitor.
///
public abstract String Name { get; }
#endregion
// Lifecycle
#region Lifecycle
///
/// A value indicating whether the monitor is active and should be running (Default: true).
///
[SerializeField]
[Header("General - Settings")]
[Tooltip("A value indicating whether the monitor is active and should be running (Default: true).")]
private bool isActive = true;
///
/// A value indicating whether the monitor is active and should be running.
///
public bool IsActive => this.isActive;
///
/// Gets a value indicating whether the monitor has been started and is currently running.
///
public bool IsStarted { get; private set; }
///
/// Gets a value indicating whether the monitor has been paused and is currently suspended.
///
public bool IsPaused { get; private set; }
///
/// Initiates the monitoring process, enabling the monitor to start collecting and processing data.
///
public void Start()
{
// Check if the monitor is already started, if so return.
if (this.IsStarted)
{
return;
}
// Set the monitor as started.
this.IsStarted = true;
// Notify.
this.OnStart();
}
///
/// Executed when the monitor is started. Override this method to provide custom start behavior.
///
protected virtual void OnStart()
{
}
///
/// Pauses the monitoring process, temporarily suspending data collection and processing without terminating the monitor.
///
public void Pause()
{
// Check if the monitor is paused, if so return.
if (this.IsPaused)
{
return;
}
// Check if the monitor not started, if so return.
if (!this.IsStarted)
{
return;
}
// Set the monitor as paused.
this.IsPaused = true;
// Notify.
this.OnPause();
}
///
/// Executed when the monitor is paused. Override this method to provide custom pause behavior.
///
protected virtual void OnPause()
{
}
///
/// Resumes the monitoring process after a pause, allowing the monitor to continue collecting and processing data.
///
public void Resume()
{
// Check if the monitor is not paused, if so return.
if (!this.IsPaused)
{
return;
}
// Check if the monitor not started, if so return.
if (!this.IsStarted)
{
return;
}
// Set the monitor as not paused.
this.IsPaused = false;
// Notify.
this.OnResume();
}
///
/// Executed when the monitor is resumed after a pause. Override this method to provide custom resume behavior.
///
protected virtual void OnResume()
{
}
///
/// Stops and terminates the monitoring process, concluding data collection and finalizing any necessary cleanup operations.
///
public void Stop()
{
// Check if the monitor is not started, if so return.
if (!this.IsStarted)
{
return;
}
// Set the monitor as not started.
this.IsStarted = false;
// Notify.
this.OnStop();
}
///
/// Executed when the monitor is stopped. Override this method to provide custom stop behavior.
///
protected virtual void OnStop()
{
}
///
/// Executed on each Unity update cycle when the monitor is started and not paused.
///
private void Update()
{
// Check if the monitor is started and not paused.
if (!this.IsStarted || this.IsPaused)
{
return;
}
// Check if the monitor is active.
if (!this.isActive)
{
return;
}
// Notify.
this.OnUpdate();
}
///
/// Executed on each Unity update cycle when the monitor is started and not paused.
/// Override this method to implement custom update behavior.
///
protected virtual void OnUpdate()
{
}
///
/// When the monitor is destroyed, stop the monitor.
///
protected virtual void OnDestroy()
{
// Stop the monitor.
this.Stop();
}
///
/// Notifies the observers that the monitor has completed.
///
public void Dispose()
{
foreach (var var_Observer in this.observers)
{
if (var_Observer == null)
{
continue;
}
var_Observer.OnCompleted();
}
this.observers.Clear();
}
#endregion
// Observable
#region Observable
///
/// The list of observers subscribed to the monitor.
///
private List> observers = new List>();
///
/// Subscribes an observer to receive notifications of the monitor.
///
/// The observer to subscribe.
/// An object that can be used to unsubscribe the observer.
public IDisposable Subscribe(IObserver _Observer)
{
if (!this.observers.Contains(_Observer))
{
this.observers.Add(_Observer);
}
return new Unsubscriber(this.observers, _Observer);
}
///
/// Notifies all subscribed observers with the provided watched monitor subject.
///
/// The watched subject to notify observers about.
public void Notify(IWatchedSubject _Subject)
{
foreach (var var_Observer in this.observers)
{
if (var_Observer == null)
{
continue;
}
var_Observer.OnNext(_Subject);
}
}
///
/// Represents a disposable object used to unsubscribe an observer from the monitor.
///
private class Unsubscriber : IDisposable
{
private List> observers;
private IObserver observer;
///
/// Initializes a new instance of the class.
///
/// The list of observers to manage.
/// The observer to unsubscribe.
public Unsubscriber(List> observers, IObserver observer)
{
this.observers = observers;
this.observer = observer;
}
///
/// Disposes of the observer, removing it from the list of observers.
///
public void Dispose()
{
if (this.observer != null && this.observers.Contains(this.observer))
{
this.observers.Remove(this.observer);
}
}
}
#endregion
}
}