using System;

namespace Cirno.Scripts.Utils;

public static class EnumFlagsExtensions
{
    public static bool HasAllFlags<T>(this T value, T flags) where T : Enum
    {
        var valueInt = Convert.ToUInt64(value);
        var flagsInt = Convert.ToUInt64(flags);
        return (valueInt & flagsInt) == flagsInt;
    }

    public static bool HasAnyFlag<T>(this T value, T flags) where T : Enum
    {
        var valueInt = Convert.ToUInt64(value);
        var flagsInt = Convert.ToUInt64(flags);
        return (valueInt & flagsInt) != 0;
    }

    public static bool HasNoFlags<T>(this T value, T flags) where T : Enum
    {
        var valueInt = Convert.ToUInt64(value);
        var flagsInt = Convert.ToUInt64(flags);
        return (valueInt & flagsInt) == 0;
    }

    public static T AddFlags<T>(this T value, T flags) where T : Enum
    {
        var valueInt = Convert.ToUInt64(value);
        var flagsInt = Convert.ToUInt64(flags);
        return (T)Enum.ToObject(typeof(T), valueInt | flagsInt);
    }

    public static T RemoveFlags<T>(this T value, T flags) where T : Enum
    {
        var valueInt = Convert.ToUInt64(value);
        var flagsInt = Convert.ToUInt64(flags);
        return (T)Enum.ToObject(typeof(T), valueInt & ~flagsInt);
    }

    public static T ToggleFlags<T>(this T value, T flags) where T : Enum
    {
        var valueInt = Convert.ToUInt64(value);
        var flagsInt = Convert.ToUInt64(flags);
        return (T)Enum.ToObject(typeof(T), valueInt ^ flagsInt);
    }
}