#include "main.h"
#include <lua.h>
#include <lauxlib.h>
#include "gfx.h"
#include "lib_surface.h"

static int lib_clear(lua_State *L)
{
	int color = luaL_optint(L,1,0);
	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,(color>>16)&0xFF,(color>>8)&0xFF,color&0xFF));
	return 0;
}

static int lib_draw(lua_State *L)
{
	// Read the arguments
	Lua_Surface *s = luaL_checkudata(L,1,"SDL_Surface"); // surf to blit
	SDL_Rect src={0,0,s->surf->w,s->surf->h},dst={0,0,0,0};
	if (lua_istable(L,2)) { // src rect
		lua_pushinteger(L,1);
		lua_gettable(L,2);
		src.x = (Uint32)(luaL_optnumber(L,-1,src.x)*(double)SCREENSCALE) % s->surf->w;
		lua_pop(L,1);

		lua_pushinteger(L,2);
		lua_gettable(L,2);
		src.y = (Uint32)(luaL_optnumber(L,-1,src.y)*(double)SCREENSCALE) % s->surf->h;
		lua_pop(L,1);

		lua_pushinteger(L,3);
		lua_gettable(L,2);
		src.w = luaL_optnumber(L,-1,src.w)*(double)SCREENSCALE;
		lua_pop(L,1);

		lua_pushinteger(L,4);
		lua_gettable(L,2);
		src.h = luaL_optnumber(L,-1,src.h)*(double)SCREENSCALE;
		lua_pop(L,1);
	}
	if (lua_istable(L,3)) { // dst rect
		lua_pushinteger(L,1);
		lua_gettable(L,3);
		dst.x = luaL_optnumber(L,-1,dst.x)*(double)SCREENSCALE;
		lua_pop(L,1);

		lua_pushinteger(L,2);
		lua_gettable(L,3);
		dst.y = luaL_optnumber(L,-1,dst.y)*(double)SCREENSCALE;
		lua_pop(L,1);
	}

	// Start at the beginning
	while (src.x < 0)
		src.x += s->surf->w;
	while (src.y < 0)
		src.y += s->surf->h;
	// Stay on the texture
	if (src.x >= s->surf->w)
		src.x %= s->surf->w;
	if (src.y >= s->surf->h)
		src.y %= s->surf->h;
	// Draw it! :3
	SDL_BlitSurface(s->surf,&src,screen,&dst);

	// Stuff to simulate hardware texture wrapping stuffs.
	const SDL_Rect osrc=src,odst=dst;
	while (src.y + src.h > s->surf->h) { // Properly loop textures that are too tall
		Uint16 stopped_at = s->surf->h-src.y%s->surf->h;
		src.h -= stopped_at;
		src.y = (src.y+stopped_at)%s->surf->h;
		dst.y += stopped_at;
		SDL_BlitSurface(s->surf,&src,screen,&dst);
	}
	while (src.x + src.w > s->surf->w) { // Properly loop textures that are too wide
		Uint16 stopped_at = s->surf->w-src.x%s->surf->w;
		src.w -= stopped_at;
		src.x = (src.x+stopped_at)%s->surf->w;
		dst.x += stopped_at;
		src.y = osrc.y;
		src.h = osrc.h;
		dst.y = odst.y;
		SDL_BlitSurface(s->surf,&src,screen,&dst);
		while (src.y + src.h > s->surf->h) { // Too wide AND too tall!
			Uint16 stopped_at = s->surf->h-src.y%s->surf->h;
			src.h -= stopped_at;
			src.y = (src.y+stopped_at)%s->surf->h;
			dst.y += stopped_at;
			SDL_BlitSurface(s->surf,&src,screen,&dst);
		}
	}
	return 0;
}

static luaL_Reg lib[] = {
	{"clear",lib_clear},
	{"draw",lib_draw},
	{NULL,NULL}
};

void agllib_screen(lua_State *L)
{
	luaL_newmetatable(L,"screen");
	lua_pushvalue(L,-1);
	lua_setfield(L,-2,"__index");
	luaL_register(L,NULL,lib);
	lua_pop(L,1);
}
