// --------------------------------------------------
// UnityInjector - SafeConsole.cs
// Copyright (c) Usagirei 2015 - 2015
// --------------------------------------------------

using System;
using System.Reflection;

namespace UnityInjector.ConsoleUtil;

/// <summary>
///     Console class with safe handlers for Unity 4.x, which does not have a proper Console implementation
/// </summary>
internal static class SafeConsole
{
    private static GetColorDelegate _getBackgroundColor;
    private static SetColorDelegate _setBackgroundColor;

    private static GetColorDelegate _getForegroundColor;
    private static SetColorDelegate _setForegroundColor;

    private static GetStringDelegate _getTitle;
    private static SetStringDelegate _setTitle;

    static SafeConsole()
    {
        var tConsole = typeof(Console);
        InitColors(tConsole);
    }

    public static bool BackgroundColorExists { get; private set; }

    public static ConsoleColor BackgroundColor
    {
        get => _getBackgroundColor();
        set => _setBackgroundColor(value);
    }

    public static bool ForegroundColorExists { get; private set; }

    public static ConsoleColor ForegroundColor
    {
        get => _getForegroundColor();
        set => _setForegroundColor(value);
    }

    public static bool TitleExists { get; private set; }

    public static string Title
    {
        get => _getTitle();
        set => _setTitle(value);
    }

    private static void InitColors(Type tConsole)
    {
        const BindingFlags BINDING_FLAGS = BindingFlags.Public | BindingFlags.Static;

        var gfc = tConsole.GetMethod("get_ForegroundColor", BINDING_FLAGS);
        var sfc = tConsole.GetMethod("set_ForegroundColor", BINDING_FLAGS);

        var gbc = tConsole.GetMethod("get_BackgroundColor", BINDING_FLAGS);
        var sbc = tConsole.GetMethod("set_BackgroundColor", BINDING_FLAGS);

        var gtt = tConsole.GetMethod("get_Title", BINDING_FLAGS);
        var stt = tConsole.GetMethod("set_Title", BINDING_FLAGS);

        _setForegroundColor = sfc != null
                                  ? (SetColorDelegate) Delegate.CreateDelegate(typeof(SetColorDelegate), sfc)
                                  : value => { };

        _setBackgroundColor = sbc != null
                                  ? (SetColorDelegate) Delegate.CreateDelegate(typeof(SetColorDelegate), sbc)
                                  : value => { };

        _getForegroundColor = gfc != null
                                  ? (GetColorDelegate) Delegate.CreateDelegate(typeof(GetColorDelegate), gfc)
                                  : () => ConsoleColor.Gray;

        _getBackgroundColor = gbc != null
                                  ? (GetColorDelegate) Delegate.CreateDelegate(typeof(GetColorDelegate), gbc)
                                  : () => ConsoleColor.Black;

        _getTitle = gtt != null
                        ? (GetStringDelegate) Delegate.CreateDelegate(typeof(GetStringDelegate), gtt)
                        : () => string.Empty;

        _setTitle = stt != null
                        ? (SetStringDelegate) Delegate.CreateDelegate(typeof(SetStringDelegate), stt)
                        : value => { };

        BackgroundColorExists = _setBackgroundColor != null && _getBackgroundColor != null;
        ForegroundColorExists = _setForegroundColor != null && _getForegroundColor != null;
        TitleExists = _setTitle != null && _getTitle != null;
    }

    private delegate ConsoleColor GetColorDelegate();

    private delegate void SetColorDelegate(ConsoleColor value);

    private delegate string GetStringDelegate();

    private delegate void SetStringDelegate(string value);
}
