using static System.ConsoleKey;

namespace InnovEnergy.Lib.Utils;

public static class ConsoleUtils
{
    public static T WriteLine<T>(this T t, ConsoleColor foregroundColor)
    {
        var c = Console.ForegroundColor;

        Console.ForegroundColor = foregroundColor;
        Console.WriteLine(t);
        Console.ForegroundColor = c;

        return t;
    }

    public static T WriteLine<T>(this T t)
    {
        Console.WriteLine(t);
        return t;
    }

    public static T WriteLine<T>(this T t, ConsoleColor color, params String[] more)
    {
        var c = Console.ForegroundColor;

        Console.ForegroundColor = color;
        Console.WriteLine(t + " " + more.JoinWith(" "));
        Console.ForegroundColor = c;

        return t;
    }

    public static T WriteLine<T>(this T t, params String[] more)
    {
        Console.WriteLine(t + " " + more.JoinWith(" "));
        return t;
    }

    public static T Write<T>(this T t, ConsoleColor color)
    {
        var c = Console.ForegroundColor;

        Console.ForegroundColor = color;
        Console.Write(t);
        Console.ForegroundColor = c;

        return t;
    }

    public static T Write<T>(this T t)
    {
        Console.Write(t);
        return t;
    }

    public static T Write<T>(this T t, ConsoleColor color, params String[] more)
    {
        var c = Console.ForegroundColor;

        Console.ForegroundColor = color;
        Console.Write(t + " " + more.JoinWith(" "));
        Console.ForegroundColor = c;

        return t;
    }

    public static T Write<T>(this T t, params String[] more)
    {
        Console.Write(t + " " + more.JoinWith(" "));
        return t;
    }

    public static T WriteLine<T>(this T t, ConsoleColor fgColor, ConsoleColor bgColor, Boolean invert = false)
    {
        var fg = Console.ForegroundColor;
        var bg = Console.BackgroundColor;

        Console.ForegroundColor = invert ? bgColor : fgColor;
        Console.BackgroundColor = invert ? fgColor : bgColor;
        Console.WriteLine(t);
        Console.BackgroundColor = bg;
        Console.ForegroundColor = fg;

        return t;
    }

    public static T Write<T>(this T t, ConsoleColor fgColor, ConsoleColor bgColor, Boolean invert = false)
    {
        var fg = Console.ForegroundColor;
        var bg = Console.BackgroundColor;

        Console.ForegroundColor = invert ? bgColor : fgColor;
        Console.BackgroundColor = invert ? fgColor : bgColor;
        Console.Write(t);
        Console.BackgroundColor = bg;
        Console.ForegroundColor = fg;

        return t;
    }

    public static String Input(this String prompt)
    {
        (prompt.TrimEnd(' ') + " ").Write();

        var input = "";

        while (true)
        {
            var keyInfo = Console.ReadKey(intercept: true);
            var key     = keyInfo.Key;
            var keyChar = keyInfo.KeyChar;

            if (key == Enter)
            {
                Console.WriteLine("");
                return input;
            }

            if (key == Backspace && input.Length > 0)
            {
                input = input.Substring(0, input.Length - 1);
                Console.Write("\b \b");
            }
            else if (!Char.IsControl(keyChar))
            {
                input += keyChar;
                Console.Write(keyChar);
            }
        }
    }

    public static String PasswordEntry(this String prompt)
    {
        (prompt.TrimEnd(' ') + " ").Write();

        var password = "";

        while (true)
        {
            var keyInfo = Console.ReadKey(intercept: true);
            var key     = keyInfo.Key;
            var keyChar = keyInfo.KeyChar;

            if (key == Backspace && password.Length > 0)
            {
                password = password.Substring(0, password.Length - 1);
                Console.Write("\b \b");
            }
            else if (!Char.IsControl(keyChar) || key == Enter)
            {
                if (password.Length > 0)
                    Console.Write("\b*");

                if (key == Enter)
                {
                    Console.WriteLine();
                    return password;
                }
                else
                {
                    Console.Write(keyChar);
                    password += keyChar;
                }
            }
        }
    }
}