namespace EpsonReceiptPrinter;

public static class EscPosCommands
{
    public static readonly byte[] Initialize = [0x1B, 0x40];

    public static readonly byte[] BoldOn = [0x1B, 0x45, 0x01];
    public static readonly byte[] BoldOff = [0x1B, 0x45, 0x00];

    public static readonly byte[] UnderlineOn = [0x1B, 0x2D, 0x01];
    public static readonly byte[] UnderlineOff = [0x1B, 0x2D, 0x00];

    public static readonly byte[] AlignLeft = [0x1B, 0x61, 0x00];
    public static readonly byte[] AlignCenter = [0x1B, 0x61, 0x01];
    public static readonly byte[] AlignRight = [0x1B, 0x61, 0x02];

    public static readonly byte[] FontA = [0x1B, 0x4D, 0x00];
    public static readonly byte[] FontB = [0x1B, 0x4D, 0x01];

    public static byte[] Feed(int lines)
    {
        if (lines < 0 || lines > 255)
        {
            throw new ArgumentOutOfRangeException(nameof(lines));
        }

        return [0x1B, 0x64, (byte)lines];
    }

    public static byte[] CutFull() => [0x1D, 0x56, 0x00];

    public static byte[] CutPartial() => [0x1D, 0x56, 0x01];

    public static byte[] OpenCashDrawer() => [0x1B, 0x70, 0x00, 0x19, 0xFA];

    public static byte[] SelectCodePage(PrinterCodePage codePage) => [0x1B, 0x74, (byte)codePage];

    public static byte[] TextSize(TextSize size) =>
        size switch
        {
            TextSize.Normal => [0x1D, 0x21, 0x00],
            TextSize.DoubleWidth => [0x1D, 0x21, 0x10],
            TextSize.DoubleHeight => [0x1D, 0x21, 0x01],
            TextSize.DoubleWidthAndHeight => [0x1D, 0x21, 0x11],
            _ => [0x1D, 0x21, 0x00]
        };

    public static byte[] TextSize(int widthMultiplier, int heightMultiplier)
    {
        if (widthMultiplier < 1 || widthMultiplier > 8)
        {
            throw new ArgumentOutOfRangeException(nameof(widthMultiplier));
        }

        if (heightMultiplier < 1 || heightMultiplier > 8)
        {
            throw new ArgumentOutOfRangeException(nameof(heightMultiplier));
        }

        var value = (byte)(((widthMultiplier - 1) << 4) | (heightMultiplier - 1));
        return [0x1D, 0x21, value];
    }
}
