using System;

namespace BepInEx.Logging;

/// <summary>
///     The level, or severity of a log entry.
/// </summary>
[Flags]
public enum LogLevel
{
    /// <summary>
    ///     No level selected.
    /// </summary>
    None = 0,

    /// <summary>
    ///     A fatal error has occurred, which cannot be recovered from.
    /// </summary>
    Fatal = 1,

    /// <summary>
    ///     An error has occured, but can be recovered from.
    /// </summary>
    Error = 2,

    /// <summary>
    ///     A warning has been produced, but does not necessarily mean that something wrong has happened.
    /// </summary>
    Warning = 4,

    /// <summary>
    ///     An important message that should be displayed to the user.
    /// </summary>
    Message = 8,

    /// <summary>
    ///     A message of low importance.
    /// </summary>
    Info = 16,

    /// <summary>
    ///     A message that would likely only interest a developer.
    /// </summary>
    Debug = 32,

    /// <summary>
    ///     All log levels.
    /// </summary>
    All = Fatal | Error | Warning | Message | Info | Debug
}

/// <summary>
///     Helper methods for log level handling.
/// </summary>
public static class LogLevelExtensions
{
    /// <summary>
    ///     Gets the highest log level when there could potentially be multiple levels provided.
    /// </summary>
    /// <param name="levels">The log level(s).</param>
    /// <returns>The highest log level supplied.</returns>
    public static LogLevel GetHighestLevel(this LogLevel levels)
    {
        var enums = Enum.GetValues(typeof(LogLevel));
        Array.Sort(enums);

        foreach (LogLevel e in enums)
            if ((levels & e) != LogLevel.None)
                return e;

        return LogLevel.None;
    }

    /// <summary>
    ///     Returns a translation of a log level to it's associated console colour.
    /// </summary>
    /// <param name="level">The log level(s).</param>
    /// <returns>A console color associated with the highest log level supplied.</returns>
    public static ConsoleColor GetConsoleColor(this LogLevel level)
    {
        level = GetHighestLevel(level);
        return level switch
        {
            LogLevel.Fatal   => ConsoleColor.Red,
            LogLevel.Error   => ConsoleColor.DarkRed,
            LogLevel.Warning => ConsoleColor.Yellow,
            LogLevel.Message => ConsoleColor.White,
            LogLevel.Info    => ConsoleColor.DarkGray,
            LogLevel.Debug   => ConsoleColor.DarkGray,
            _                => ConsoleColor.Gray
        };
    }
}
