#include <instance.h>
#include <gfx.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>

static unsigned char line_g;
static bool line_g_flip;

void instance_cyclic(void)
{
    if (!line_g_flip)
    {
        if ((line_g += 5) >= UCHAR_MAX)
            line_g_flip ^= true;
    }
    else if (!(line_g -= 5))
        line_g_flip ^= true;
}

static int render_sprite(struct sprite *const s,
    const struct instance_render_off *const off, const short x, const short y)
{
    s->x = off ? x + off->x : x;
    s->y = off ? y + off->y : y;

    const int ret = sprite_sort(s);

    if (ret)
        fprintf(stderr, "%s: sprite_sort failed\n", __func__);

    return ret;
}

static void render_quad(const struct instance_render_quad *const rq,
    const struct instance_render_off *const off, const short x, const short y)
{
    struct quad *const q = rq->q;
    const short x0 = x + off->x, x1 = x0 + rq->w - 1;

    if (rq->xflip)
    {
        q->x0 = q->x2 = x1;
        q->x1 = q->x3 = x0;
        q->u0 = q->u2 = rq->u;
        q->u1 = q->u3 = rq->u + rq->w - 1;
    }
    else
    {
        q->x0 = q->x2 = x0;
        q->x1 = q->x3 = x1;
        q->u0 = q->u2 = rq->u;
        q->u1 = q->u3 = rq->u + rq->w - 1;
    }

    const short y0 = y + off->y, y1 = y0 + rq->h - 1;

    q->y0 = q->y1 = y0;
    q->y2 = q->y3 = y1;
    quad_sort(q);
}

int instance_render(const struct instance_render_cfg *const cfg)
{
    const struct instance *const i = cfg->i;
    short x, y;

    if (camera_translate(cfg->cam, &i->r, &x, &y))
    {
        const struct instance_render_off *const off = cfg->off;

        switch (cfg->prim_type)
        {
            case INSTANCE_RENDER_CFG_SPRITE:
                render_sprite(cfg->prim.s, off, x, y);
                break;

            case INSTANCE_RENDER_CFG_QUAD:
                render_quad(cfg->prim.quad, off, x, y);
                break;
        }
    }

    return 0;
}

int instance_render_target(const struct instance *const i,
    const struct camera *const cam)
{
    return 0;
}
