#include <time.h>
#include <stdlib.h>
#include <pspdisplay.h>
extern "C" {
#include "share.h"
}
// if the timer is running:
// measuredTime is the value of the last call to getCurrentMilliseconds
// offset is the value of startTime
//
// if the timer is stopped:
// measuredTime is 0
// offset is the value time() returns on stopped timers

typedef struct
{
	clock_t measuredTime;
	clock_t offset;
} Timer;

UserdataStubs(Timer, Timer*)

static clock_t getCurrentMilliseconds()
{
	return clock() / clock_t(CLOCKS_PER_SEC *0.001);
}

static int Timer_new(lua_State *L)
{
	Timer** luaTimer = pushTimer(L);
	Timer* timer = (Timer*) malloc(sizeof(Timer));
	*luaTimer = timer;
	timer->measuredTime = getCurrentMilliseconds();
	timer->offset = lua_gettop(L) == 1 ? luaL_checkint(L, 1) : 0;
	return 1;
}

static int Timer_start(lua_State *L)
{
	Timer* timer = *toTimer(L, 1);
	if (timer->measuredTime) {
		// timer is running
		clock_t currentTime = getCurrentMilliseconds();
		lua_pushnumber(L, currentTime - timer->measuredTime + timer->offset);
	} else {
		// timer is stopped
		timer->measuredTime = getCurrentMilliseconds();
		lua_pushnumber(L, timer->offset);
	}
	return 1;
}

static int Timer_time(lua_State *L)
{
	Timer* timer = *toTimer(L, 1);
	if (timer->measuredTime) {
		// timer is running
		clock_t currentTime = getCurrentMilliseconds();
		lua_pushnumber(L, currentTime - timer->measuredTime + timer->offset);
	} else {
		// timer is stopped
		lua_pushnumber(L, timer->offset);
	}
	return 1;
}

static int Timer_stop(lua_State *L)
{
	Timer* timer = *toTimer(L, 1);
	if (timer->measuredTime) {
		// timer is running
		clock_t currentTime = getCurrentMilliseconds();
		timer->offset = currentTime - timer->measuredTime + timer->offset;
		timer->measuredTime = 0;
	}
	lua_pushnumber(L, timer->offset);
	return 1;
}


static int Timer_reset(lua_State *L)
{
	Timer* timer = *toTimer(L, 1);
	if (timer->measuredTime) {
		// timer is running
		clock_t currentTime = getCurrentMilliseconds();
		lua_pushnumber(L, currentTime - timer->measuredTime + timer->offset);
	} else {
		// timer is stopped
		lua_pushnumber(L, timer->offset);
	}
	timer->offset = lua_gettop(L) == 2 ? luaL_checkint(L, 2) : 0;
	timer->measuredTime = 0;
	return 1;
}


static int Timer_free(lua_State *L)
{
	free(*toTimer(L, 1));
	return 0;
}

static const luaL_reg Timer_methods[] = {
	{"new", Timer_new},
	{"start", Timer_start},
	{"time", Timer_time},
	{"stop", Timer_stop},
	{"reset", Timer_reset},
	{0,0}
};

static const luaL_reg Timer_meta[] = {
	{"__gc", Timer_free},
	{0,0}
};

UserdataRegister(Timer, Timer_methods, Timer_meta)

extern "C" void timer_init(lua_State *L)
{
	Timer_register(L);
}
