#include "sys_interaction.h"
#include "system.h"
#include "sys_vr.h"
#include "sys_vr_passthru.h"
#include "sys_render.h"
#include "sys_undo.h"

#define GROW_FACTOR (1.004f)
#define GROW_MIN (0.05f)
#define GROW_MAX (2.00f)

#define PREVIEW_BASE {0.0f,0.0f,0.0f,1.0f};
#define PREVIEW_SIDE {1.0f,0.0f,0.0f,0.0f};
#define PREVIEW_UP   {0.0f,0.7071067811865476f,-0.7071067811865476f,0.0f};

static uint32_t tracked_id = 0xfffffffful;
static unsigned toolidx = 0;
static float new_width = 1.0f;
static float new_height = 0.618f;
static yrTexture tex_fill = NULL;
static int trig_wasdown = 0;
static yrTexture tpadbut_create = NULL;
static yrTexture tpadbut_create_glow[4] = {NULL};

static void create_shutdown(void);
static void create_settrackedid(uint32_t, unsigned);
static void create_tick(void);
static int  create_canfreeze(void);
static void create_forceidle(void);
static int	create_getpokepos(vec4f* pos, vec4f* dir, float* len) {return 0;}

int tool_create_init(func_tool_shutdown* st_sd,
					 func_tool_settrackedid* ft_sti,
					 func_tool_tick* ft_t,
					 func_tool_canfreeze* ft_cf,
					 func_tool_forceidle* ft_fi,
					 func_tool_getpokepos* ft_gpp,
					 func_tool_renderwindow* ft_rw,
					 func_tool_poke* ft_p)
{
	*st_sd	= create_shutdown;
	*ft_sti	= create_settrackedid;
	*ft_t	= create_tick;
	*ft_cf	= create_canfreeze;
	*ft_fi	= create_forceidle;
	*ft_gpp = create_getpokepos;
	*ft_rw	= nullfunc;
	*ft_p	= nullfunc;

	tracked_id = 0xfffffffful;
	toolidx = 0;
	trig_wasdown = 0;
	tex_fill = yrTexture_loadfile("data/vr/empty.png"); if(!tex_fill) return -1;
	tpadbut_create			= yrTexture_loadfile("data/vr/tpadbut_create.png");		if(!tpadbut_create) return -1;
	tpadbut_create_glow[0]	= yrTexture_loadfile("data/vr/tpadbut_create_right.png");	if(!tpadbut_create_glow[0]) return -1;
	tpadbut_create_glow[1]	= yrTexture_loadfile("data/vr/tpadbut_create_up.png");		if(!tpadbut_create_glow[1]) return -1;
	tpadbut_create_glow[2]	= yrTexture_loadfile("data/vr/tpadbut_create_left.png");	if(!tpadbut_create_glow[2]) return -1;
	tpadbut_create_glow[3]	= yrTexture_loadfile("data/vr/tpadbut_create_down.png");	if(!tpadbut_create_glow[3]) return -1;

	return 0;
}

static void create_shutdown(void)
{
	yrTexture_unload(tpadbut_create_glow[0]);
	yrTexture_unload(tpadbut_create_glow[1]);
	yrTexture_unload(tpadbut_create_glow[2]);
	yrTexture_unload(tpadbut_create_glow[3]);
	yrTexture_unload(tpadbut_create);
	tpadbut_create_glow[3] = NULL;
	tpadbut_create_glow[2] = NULL;
	tpadbut_create_glow[1] = NULL;
	tpadbut_create_glow[0] = NULL;
	tpadbut_create = NULL;
	yrTexture_unload(tex_fill);
	tex_fill = NULL;
}

static void create_settrackedid(uint32_t tr_id, unsigned tool_idx)
{
	tracked_id = tr_id;
	toolidx = tool_idx;
}

static void create_tick(void)
{
	VRControllerState_t cbuttons = {0};
	ovrSystem_GetControllerState(tracked_id, &cbuttons);
	mat4f mat = yrVR_world_from_tracked(tracked_id);
	vec4i off = yrVR_get_coord_offset();
	yrColor color = yrInteraction_getpencolor();

	float touchx = cbuttons.rAxis[EVRButtonId_k_EButton_SteamVR_Touchpad - EVRButtonId_k_EButton_Axis0].x;
	float touchy = cbuttons.rAxis[EVRButtonId_k_EButton_SteamVR_Touchpad - EVRButtonId_k_EButton_Axis0].y;
	int touchd = 0!=(cbuttons.ulButtonPressed & (1ull << EVRButtonId_k_EButton_SteamVR_Touchpad));

	//draw buttons
	yrRenderTrackedOverlay_clear(toolidx);
	if(touchd || touchx != 0.0f || touchy != 0.0f) {
		int glowidx;
		if(fabsf(touchx) > fabsf(touchy))	glowidx = (touchx > 0.0f) ? 0:2;
		else								glowidx = (touchy > 0.0f) ? 1:3;
		yrRenderTrackedOverlay_draw(toolidx, tpadbut_create_glow[glowidx], -1.0f, -1.0f, 1.0f, 1.0f, touchd ? 0xFFFF8010 : 0x80FF8010);
	}
	yrRenderTrackedOverlay_draw(toolidx, tpadbut_create, -1.0f, -1.0f, 1.0f, 1.0f, 0xFFFFFFFF);
	yrRenderTrackedOverlay_render(toolidx);

	//detect resize presses
	if(touchd) {
		if(touchx > touchy) {
			if(touchx > -touchy) {
				//grow h
				new_width *= GROW_FACTOR;
				if(new_width > GROW_MAX) new_width = GROW_MAX;
			} else {
				//shrink v
				new_height /= GROW_FACTOR;
				if(new_height < GROW_MIN) new_height = GROW_MIN;
			}
		} else {
			if(touchx > -touchy) {
				//grow v
				new_height *= GROW_FACTOR;
				if(new_height > GROW_MAX) new_height = GROW_MAX;
			} else {
				//shrink h
				new_width /= GROW_FACTOR;
				if(new_width < GROW_MIN) new_width = GROW_MIN;
			}
		}
	}
	//create preview quad
	yrQuad prev_quad = {0};
	prev_quad.height = new_height;
	prev_quad.width = new_width;
	prev_quad.uv_back[0][0] = 0.0f;
	prev_quad.uv_back[0][1] = 0.0f;
	prev_quad.uv_back[1][0] = 1.0f;
	prev_quad.uv_back[1][1] = 1.0f;
	prev_quad.texture_bg = 125;
	
	//preview position
	vec4f v[3];
	vec4f pside = PREVIEW_SIDE;
	vec4f pup = PREVIEW_UP;
	vec4f pbase = PREVIEW_BASE;
	v[0] = vec4f_mul(-new_width / 2, pside);
	v[1] = vec4f_neg(v[0]);
	v[2] = vec4f_add(v[0], vec4f_mul(new_height, pup));
	v[0] = mat4f_apply(mat, vec4f_add(pbase, v[0]));
	v[1] = mat4f_apply(mat, vec4f_add(pbase, v[1]));
	v[2] = mat4f_apply(mat, vec4f_add(pbase, v[2]));
	prev_quad.v[0] = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, v[0])));
	prev_quad.v[1] = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, v[1])));
	prev_quad.v[2] = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, v[2])));

	//preview normal
	prev_quad.normal = mat4f_apply(mat, vec3f_cross(pside, pup));

	//detect create trigger
	float trig = cbuttons.rAxis[EVRButtonId_k_EButton_SteamVR_Trigger - EVRButtonId_k_EButton_Axis0].x;
	int trig_down = trig == 1.0f;	
	if(!trig_wasdown && trig_down) {
		//trigger is down now but wasn't in last frame
		static unsigned char bar = 0;
		yrQuad* foo = yrQuadStore_add(&prev_quad);
		foo->color = yrInteraction_getbgcolor();
		yrUndo_append(utAdd, NULL, foo, NULL, foo->ext->tiles);
		trig_wasdown = 1;
	}
	trig_wasdown = trig_wasdown && trig > 0.5f;
	//render preview quad	
	yrColor prevclr = yrInteraction_getbgcolor();
	prevclr = ((prevclr / 2) & 0x00FFFFFF) | 0x80808080;
	yrRenderOverlay_clear(OVERLAY_CREATE);
	yrRenderOverlay_draw(OVERLAY_CREATE, tex_fill, 0.0f, 0.0f, 8.0f, 8.0f, prevclr);
	yrRenderOverlay_render(OVERLAY_CREATE, &prev_quad, 0);
}

static int create_canfreeze(void)
{
	return 1;
}

static void	create_forceidle(void)
{
	; //do nothing
}
