#ifndef TWN_DRAW_H
#define TWN_DRAW_H

#include "twn_types.h"
#include "twn_option.h"
#include "twn_engine_api.h"

#include <stdbool.h>

/* pushes a sprite onto the sprite render queue */
/* TODO: combine flip_x and flip_y into a flip_mask with enum */
TWN_API void draw_sprite(char const *texture,
                         Rect        rect,
                         Rect const *texture_region,    /* optional, default: NULL */
                         Color       color,             /* optional, default: all 255 */
                         float       rotation,          /* optional, default: 0 */
                         bool        flip_x,            /* optional, default: false */
                         bool        flip_y,            /* optional, default: false */
                         bool        stretch);          /* optional, default: true */

/* pushes a filled rectangle onto the rectangle render queue */
TWN_API void draw_rectangle(Rect rect, Color color);

/* pushes a filled circle onto the circle render queue */
/* note that its edges may look jagged with a radius larger than 2048 */
TWN_API void draw_circle(Vec2 position, float radius, Color color);

/* TODO: have font optional, with something minimal coming embedded */
TWN_API void draw_text(char const *string,
                       Vec2        position,
                       float       height,              /* optional, default: 22 */
                       Color       color,               /* optional, default: all 0 */
                       char const *font);               /* optional, default: NULL */


TWN_API float draw_text_width(char const *string,
                              float       height,       /* optional, default: 22 */
                              char const *font);        /* optional, default: NULL */

TWN_API void draw_nine_slice(char const *texture,
                             Vec2        corners,
                             Rect        rect,
                             float       border_thickness,  /* optional, default: 0 */
                             Color       color);            /* optional, default: all 255 */

TWN_API void draw_line(Vec2 start,
                       Vec2 finish,
                       float thickness, /* optional, default: 1 */
                       Color color);    /* optional, default: all 255 */

/* TODO: combine with draw_rectangle()? */
TWN_API void draw_box(Rect rect,
                      float thickness,  /* optional, default: 1 */
                      Color color);     /* optional, default: all 255 */

/* pushes a textured 3d triangle onto the render queue */
/* texture coordinates are in pixels */
TWN_API void draw_triangle(char const *texture,
                           Vec3        v0,
                           Vec3        v1,
                           Vec3        v2,
                           Vec2        uv0,
                           Vec2        uv1,
                           Vec2        uv2,
                           Color       c0,      /* optional, default: all 255 */
                           Color       c1,      /* optional, default: all 255 */
                           Color       c2);     /* optional, default: all 255 */

/* TODO: double sided option */
TWN_API void draw_quad(char const *texture,
                       Vec3        v0,          /* upper-left */
                       Vec3        v1,          /* bottom-left */
                       Vec3        v2,          /* bottom-right */
                       Vec3        v3,          /* upper-right */
                       Rect        texture_region,
                       Color       color);      /* optional, default: all 255 */

TWN_API void draw_billboard(const char *texture,
                            Vec3 position,
                            Vec2 size,
                            Color color,        /* optional, default: all 255 */
                            bool cylindrical);  /* optional, default: false */

/* sets a perspective 3d camera to be used for all 3d commands */
/* fov = 0 corresponds to orthographic projection */
TWN_API void draw_camera(Vec3 position,
                         Vec3 direction,        /* optional, default: (0, 0, -1) */
                         Vec3 up,               /* optional, default: (0, 1, 0) */
                         float fov,             /* optional, default: PI / 6 * 3 (90 degrees) */
                         float zoom);           /* optional, default: 1 */

/* same as draw_camera(), but with first person controller in mind */
/* direction and up vectors are inferred from roll, pitch and yaw parameters (in radians) */
/* return value is direction and up vectors, so that you can use them in logic (such as controllers) */
typedef struct DrawCameraFromPrincipalAxesResult {
    Vec3 direction;
    Vec3 up;
} DrawCameraFromPrincipalAxesResult;
TWN_API DrawCameraFromPrincipalAxesResult
draw_camera_from_principal_axes(Vec3 position,
                                float roll,   /* optional, default: 0 */
                                float pitch,  /* optional, default: 0 */
                                float yaw,    /* optional, default: 0 */
                                float fov,    /* optional, default: PI / 6 * 3 (90 degrees) */
                                float zoom);  /* optional, default: 1 */

/* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */
TWN_API void draw_skybox(const char *textures);


#ifndef TWN_NOT_C

typedef struct DrawSpriteArgs {
    char const *texture;
    Rect rect;

    m_option_list(
        Rect,    texture_region,
        Color,   color,
        float,   rotation,
        bool,    flip_x,
        bool,    flip_y,
        bool,    stretch )
} DrawSpriteArgs;

TWN_API void draw_sprite_args(DrawSpriteArgs args);
#define m_sprite(...) (draw_sprite_args((DrawSpriteArgs){__VA_ARGS__}))

/* TODO: define more */

#endif /* TWN_NOT_C */

#endif
