(ffi:clines "
#include <SDL2/SDL.h>

SDL_Renderer *renderer;
SDL_Window *window;
SDL_Event e;

const Uint8 *state;

int mx, my; Uint32 mdown;
int quitted;
")

(Defpackage "jam-no-theme" (:use cl) (:nicknames :ja))

(in-package :ja)


(defmacro game ((&rest shared-vars)
               (&rest shared-declares)
               update-closures)
`(let ,shared-vars
  ,(append '(declare) shared-declares)
  (ffi:c-progn ,(mapcar 'car shared-vars)
   "

if (SDL_Init(SDL_INIT_VIDEO) < 0) {
       SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
           \"Failed to init %s\",
           SDL_GetError());
       " (error "failed to SDL_Init(video)") "
}

if (SDL_CreateWindowAndRenderer(640,480,SDL_WINDOW_RESIZABLE,
       &window, &renderer)) {
       SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
           \"Failed to create w & r%s\",
           SDL_GetError());
       " (error "failed to create window and renderer") "
}

quitted = 0;
for (;;) {"
       "
       while(SDL_PollEvent(&e))
           if (e.type == SDL_QUIT) quitted = 1;
           else if (e.type == SDL_KEYDOWN)
               switch (e.key.keysym.sym) {
               case SDLK_q:
                   quitted = 1;
                   break;
               }
       if (quitted) break;

       mdown = SDL_GetMouseState(&mx, &my);
       "
       "
       SDL_SetRenderDrawColor(renderer, 0, 10, 20, 255);
       SDL_RenderClear(renderer);"

       (mapcar 'funcall ,update-closures)

       "
       SDL_RenderPresent(renderer);
       SDL_Delay(25);
       "
"}

SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();")))

(defun coord-liner (start-x below-x x-space
                    y-start y-stop y-space &key (transpose nil)
                    &aux (cur-x start-x)) "
(coord-liner (start-x below-x x-space
             y-start y-stop y-space
             &key (transpose nil)))
Return a closure that returns
(x1 y1 x2 y2) or nil when it loops,
or if transpose (y1 x1 y2 x2)
"
(lambda ()
 (reduce 'append
  (mapcar (if transpose 'reverse 'identity)
   (if (< cur-x below-x)
    (prog1 (list (list (* cur-x x-space) (* y-start y-space))
                 (list (* cur-x x-space) (* y-stop y-space)))
     (incf cur-x))
    (prog1 nil (setf cur-x start-x)))))))

(defun draw-lines-from (fun rgb) "
Calls SDL_SetRenderDrawColor and
     SDL_RenderDrawLine
with rgb and on a list from fun.
"
(lambda ()
 (loop
  for (x1 y1 x2 y2) = (funcall fun)
  for (r g b) = rgb
  while x1
  do (ffi:c-inline (r g b 255) (:int :int :int :int) nil
      "SDL_SetRenderDrawColor(renderer, #0, #1, #2, #3)"
      :one-liner t)
  do (ffi:c-inline (x1 y1 x2 y2)
      (:int :int :int :int) nil
      "SDL_RenderDrawLine(renderer, #0, #1, #2, #3)"
      :one-liner t))))

(defun xs&+s () "
I was thinking of naughts and crosses, but ultimately
I'm just drawing a grid.
"
(let* ((horiz-lines
         (draw-lines-from
         (coord-liner 1 5 50 1 4 50 :transpose nil)
         '(255 0 0)))
       (verti-lines
        (draw-lines-from
         (coord-liner 1 5 50 1 4 50 :transpose t)
         '(255 255 0)))
       (funs (list horiz-lines verti-lines)))
 (game () () funs)))