// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace WallstopStudios.UnityHelpers.Tags
{
using System;
using System.Threading;
using Core.Extension;
///
/// Opaque identifier for a specific effect application instance.
/// Use to remove or refresh one instance without affecting others.
///
///
///
/// Lifecycle: Handles are only created for and
/// effects. effects
/// apply permanently and do not produce a handle.
///
///
/// Problem solved: Distinguishes concurrent applications of the same .
/// You can remove a single stack while leaving others intact, and systems can track/refresh durations
/// per instance using the handle ID.
///
///
/// Contains:
/// - A monotonically increasing unique
/// - A reference to the applied
/// Equality and ordering are based solely on the ID.
///
///
/// Usage patterns:
///
/// // Apply and store for later removal
/// EffectHandle? maybe = target.ApplyEffect(slow);
/// if (maybe.HasValue) _activeSlows.Add(maybe.Value);
///
/// // Remove one instance (e.g., dispel one stack)
/// if (_activeSlows.Count > 0) {
/// target.RemoveEffect(_activeSlows[0]);
/// _activeSlows.RemoveAt(0);
/// }
///
/// // Refreshing timed effects (EffectHandler already supports resetDurationOnReapplication)
/// target.ApplyEffect(slow); // Reapplying can reset duration (if enabled)
///
///
///
[Serializable]
public readonly struct EffectHandle
: IEquatable,
IComparable,
IComparable
{
internal static long Id;
///
/// The AttributeEffect associated with this handle.
///
public readonly AttributeEffect effect;
///
/// The unique identifier for this effect instance.
/// This ID is globally unique and monotonically increasing.
///
public readonly long id;
///
/// Creates a new EffectHandle instance with a unique ID for the specified effect.
///
/// The AttributeEffect to create a handle for.
/// A new EffectHandle with a unique ID.
public static EffectHandle CreateInstance(AttributeEffect effect)
{
return new EffectHandle(Interlocked.Increment(ref Id), effect);
}
internal static EffectHandle CreateInstanceInternal()
{
return new EffectHandle(Interlocked.Increment(ref Id), null);
}
private EffectHandle(long id, AttributeEffect effect)
{
this.id = id;
this.effect = effect;
}
///
/// Compares this handle to another handle based on their IDs.
///
/// The handle to compare with.
///
/// A value less than 0 if this handle's ID is less than ;
/// 0 if they are equal;
/// a value greater than 0 if this handle's ID is greater than .
///
public int CompareTo(EffectHandle other)
{
return id.CompareTo(other.id);
}
///
/// Compares this handle to an object.
///
/// The object to compare with.
///
/// The comparison result if is an EffectHandle; otherwise, -1.
///
public int CompareTo(object obj)
{
if (obj is EffectHandle other)
{
return CompareTo(other);
}
return -1;
}
///
/// Determines whether this handle equals the specified object.
///
/// The object to compare with.
/// true if the object is an EffectHandle with the same ID; otherwise, false.
public override bool Equals(object obj)
{
return obj is EffectHandle other && Equals(other);
}
///
/// Determines whether this handle equals another handle by comparing their IDs.
///
/// The handle to compare with.
/// true if the IDs are equal; otherwise, false.
public bool Equals(EffectHandle other)
{
return id == other.id;
}
///
/// Returns the hash code for this handle based on its ID.
///
/// The hash code of the ID.
public override int GetHashCode()
{
return id.GetHashCode();
}
///
/// Converts this handle to a JSON string representation.
///
/// A JSON string representing this handle.
public override string ToString()
{
return this.ToJson();
}
}
}