#include <graphics.h>

static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) {
    int x, y, i;
    uint8_t color;
    int delta = pitch / 384;
    for (y = 0; y < 224; ++y) {
        for (x = 0; x < 384; x += 1) {
            color = src[(y * 384) + x];
            for (i = 0; i < delta; ++i) {
                dst[(y * pitch) + (x * delta) + i] = color;
            }
        }
    }
}

int gfxInit(GraphicsContext *gfx) {
    gfx->window = SDL_CreateWindow("Shrooms VB",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        1536, 896, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
    if (!gfx->window) {
        fprintf(stderr, "Error creating window: %s\n", SDL_GetError());
        return 1;
    }

    gfx->renderer = SDL_CreateRenderer(gfx->window, -1, 0);
    if (!gfx->renderer) {
        fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError());
        goto cleanup_window;
    }

    gfx->winSurface = SDL_GetWindowSurface(gfx->window);
    if (!gfx->winSurface) {
        fprintf(stderr, "Error getting surface: %s\n", SDL_GetError());
        goto cleanup_window;
    }

    gfx->leftEye = SDL_CreateTexture(gfx->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 384, 224);
    if (!gfx->leftEye) {
        fprintf(stderr, "Error creating left eye texture: %s\n", SDL_GetError());
        goto cleanup_window;
    }
    SDL_SetTextureColorMod(gfx->leftEye, 0xff, 0, 0);

    gfx->rightEye = SDL_CreateTexture(gfx->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 384, 224);
    if (!gfx->rightEye) {
        fprintf(stderr, "Error creating left eye texture: %s\n", SDL_GetError());
        goto cleanup_left_eye;
    }
    SDL_SetTextureColorMod(gfx->rightEye, 0, 0xc6, 0xf0);
    SDL_SetTextureBlendMode(gfx->rightEye, SDL_BLENDMODE_ADD);

    return 0;

cleanup_left_eye:
    SDL_DestroyTexture(gfx->leftEye);
cleanup_window:
    SDL_DestroyWindow(gfx->window);
    return 1;
}

void gfxDestroy(GraphicsContext *gfx) {
    SDL_DestroyTexture(gfx->rightEye);
    SDL_DestroyTexture(gfx->leftEye);
    SDL_DestroyWindow(gfx->window);
}

static void gfxUpdateEye(SDL_Texture *eye, const uint8_t *bytes) {
    void *target;
    int pitch;
    if (SDL_LockTexture(eye, NULL, &target, &pitch)) {
        fprintf(stderr, "Error locking buffer for eye: %s\n", SDL_GetError());
        return;
    }
    copyScreenTexture(target, bytes, pitch);
    SDL_UnlockTexture(eye);
}

void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes) {
    gfxUpdateEye(gfx->leftEye, bytes);
}
void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes) {
    gfxUpdateEye(gfx->rightEye, bytes);
}

void gfxRender(GraphicsContext *gfx) {
    SDL_RenderClear(gfx->renderer);
    SDL_RenderCopy(gfx->renderer, gfx->leftEye, NULL, NULL);
    SDL_RenderCopy(gfx->renderer, gfx->rightEye, NULL, NULL);
    SDL_RenderPresent(gfx->renderer);
}