#pragma once

#ifndef _swap_int16_t
#define _swap_int16_t(a, b) \
    {                       \
        int16_t t = a;      \
        a = b;              \
        b = t;              \
    }
#endif
#ifndef _diff
#define _diff(a, b) ((a > b) ? (a - b) : (b - a))
#endif

typedef enum
{
    GFX_WHITE,
    GFX_BLACK,
    GFX_INVERSE
} GFX_Color_t;

typedef enum
{
    BM_FILL_WHITE,
    BM_FILL_BLACK,
    BM_NORMAL,
    BM_INVERSE
} GFX_BitmapColor_t;

typedef enum
{
    TOP_RIGHT = 1,
    BOTTOM_RIGHT = 2,
    BOTTOM_LEFT = 4,
    TOP_LEFT = 8
} GFX_CircCorners_t;

typedef struct
{
    uint8_t width;
    uint8_t height;
    uint8_t *buffor;
} GFX_display_t;

typedef struct
{
    uint8_t width;
    uint8_t height;
    const uint8_t *bitmap;
} GFX_bitmap_t;

void DISP_drawPixel(GFX_display_t *disp, uint8_t x, uint8_t y, GFX_Color_t color);
void DISP_drawVerticalLine(GFX_display_t *disp, int16_t x, int16_t y, int16_t height, GFX_Color_t color);
void DISP_drawHorizontalLine(GFX_display_t *disp, uint8_t x, uint8_t y, uint8_t width, GFX_Color_t color);
void DISP_drawSlashLine(GFX_display_t *disp, int16_t x0, int16_t y0, int16_t x1, int16_t y1, GFX_Color_t color);
void DISP_drawRect(GFX_display_t *disp, int16_t x, int16_t y, int16_t width, int16_t height, GFX_Color_t color);
void DISP_drawFillRect(GFX_display_t *disp, int16_t x, int16_t y, int16_t width, int16_t height);
void DISP_drawCircle(GFX_display_t *disp, int16_t x0, int16_t y0, uint8_t radius, GFX_Color_t color);
void DISP_drawQuarterCircle(GFX_display_t *disp, int16_t x0, int16_t y0, uint8_t radius, GFX_CircCorners_t corner, GFX_Color_t color);
void DISP_drawRoundRect(GFX_display_t *disp, int16_t x, int16_t y, int16_t width, int16_t height, int16_t radius, GFX_Color_t color);
void DISP_drawBitmap(GFX_display_t *disp, const GFX_bitmap_t *bitmap, int8_t pos_x, int8_t pos_y, GFX_BitmapColor_t color);
void DISP_drawBitmapShift(GFX_display_t *disp, const GFX_bitmap_t *bitmap, int8_t pos_x, int8_t pos_y, uint8_t shift_left, GFX_BitmapColor_t color);
void DISP_clearRegion(GFX_display_t *disp, int16_t x, int16_t y, int16_t width, int16_t height);
void DISP_clearScreen(GFX_display_t *disp);

void DISP_drawBitmapSlow(GFX_display_t *disp, const GFX_bitmap_t *bitmap, uint8_t x, uint8_t y);
