namespace InnovEnergy.Lib.Utils;

public class TextBlock
{
    public static TextBlock Empty { get; } = new TextBlock(Array.Empty<String>());

    public IReadOnlyList<String> Lines { get; }

    public Int32 Width  => Lines.FirstOrDefault()?.Length ?? 0;
    public Int32 Height => Lines.Count;

    private TextBlock(IReadOnlyList<String> lines) => Lines = lines;

    public static TextBlock AlignLeft (params Object[] lines) => AlignHorizontal((l, w) => l.PadRight(w), lines);
    public static TextBlock AlignRight(params Object[] lines) => AlignHorizontal((l, w) => l.PadLeft(w), lines);
    public static TextBlock AlignHCenter(params Object[] lines) => AlignHorizontal((l,w) => l.PadLeft((w + l.Length) / 2).PadRight(w), lines);
    
    // public static TextBlock AlignTop(params Object[] columns)
    // {
    //     if (!columns.Any())
    //         return Empty;
    //     
    //     var cs = columns.Select(GetLines).ToArray(columns.Length);
    //     var ws = cs.Select(c => c.Count).ToArray(cs.Length);
    //     
    //     
    //     
    //
    // }
    
    
    public static TextBlock HSpace(Int32 width) => new TextBlock(new []{"".PadRight(width)});
    public static TextBlock VSpace(Int32 height) => new TextBlock(Enumerable.Repeat("", height).ToArray(height));
    public static TextBlock Space(Int32 width, Int32 height)
    {
        return new TextBlock(Enumerable.Repeat("".PadRight(width), height).ToArray(height));
    }

    private static TextBlock AlignHorizontal(Func<String, Int32, String> alignLine, Object[] lines)
    {
        if (!lines.Any())
            return Empty;

        var strings = lines
                     .SelectMany(GetLines)
                     .ToList();

        var width = strings.Max(l => l.Length);
        
        var aligned = strings
                     .Select(l => alignLine(l, width))
                     .ToArray(strings.Count);
        
        return new TextBlock(aligned);
    }
    

    private static IReadOnlyList<String> GetLines(Object l)
    {
        return l is TextBlock tb 
               ? tb.Lines
               : l.ToString()?.SplitLines() ?? new[] { "<null>" };
    }

    public override String ToString() => String.Join(Environment.NewLine, Lines);
}