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

static uint32_t tracked_id = 0xfffffffful;
static unsigned toolidx = 0;
static yrQuad* selected = NULL;
static vec4i beamdest;
static int touchdown;
static yrTexture tpadbut_delete = NULL;
static yrTexture tpadbut_cancel = NULL;
static yrTexture tpadbut_delete_glow = NULL;
static yrTexture tpadbut_cancel_glow = NULL;

#define DIST_MIN 0.0f
#define DIST_MAX 64.0f

static void delete_shutdown(void);
static void delete_settrackedid(uint32_t, unsigned);
static void delete_tick(void);
static int  delete_canfreeze(void);
static void delete_forceidle(void);
static int	delete_getpokepos(vec4f* pos, vec4f* dir, float* len) {return 0;}

int tool_delete_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	= delete_shutdown;
	*ft_sti	= delete_settrackedid;
	*ft_t	= delete_tick;
	*ft_cf	= delete_canfreeze;
	*ft_fi	= delete_forceidle;
	*ft_gpp = delete_getpokepos;
	*ft_rw	= nullfunc;
	*ft_p	= nullfunc;

	tpadbut_delete		= yrTexture_loadfile("data/vr/tpadbut_delete.png");	if(!tpadbut_delete) return -1;
	tpadbut_cancel		= yrTexture_loadfile("data/vr/tpadbut_cancel.png");	if(!tpadbut_cancel) return -1;
	tpadbut_delete_glow	= yrTexture_loadfile("data/vr/tpadbut_delete_glow.png");	if(!tpadbut_delete_glow) return -1;
	tpadbut_cancel_glow	= yrTexture_loadfile("data/vr/tpadbut_cancel_glow.png");	if(!tpadbut_cancel_glow) return -1;

	tracked_id = 0xfffffffful;
	toolidx = 0;
	selected = NULL;
	touchdown = 0;
	return 0;
}

static void delete_shutdown(void)
{
	yrTexture_unload(tpadbut_delete);
	yrTexture_unload(tpadbut_cancel);
	yrTexture_unload(tpadbut_delete_glow);
	yrTexture_unload(tpadbut_cancel_glow);
	tpadbut_delete = NULL;
	tpadbut_cancel = NULL;
	tpadbut_delete_glow = NULL;
	tpadbut_cancel_glow = NULL;
}

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

static void delete_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();

	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));
	int toucht = (touchx != 0.0f && touchy != 0.0f);

	//draw buttons
	yrRenderTrackedOverlay_clear(toolidx);
	if(!selected) {
		if(touchd || touchx != 0.0f || touchy != 0.0f) {
			yrRenderTrackedOverlay_draw(toolidx, tpadbut_delete_glow, -0.5f, -0.5f, 0.5f, 0.5f, touchd ? 0xFFFF8010 : 0x80FF8010);
		}
		yrRenderTrackedOverlay_draw(toolidx, tpadbut_delete, -0.5f, -0.5f, 0.5f, 0.5f, 0xFFFFFFFF);
	} else {
		if(touchd || touchx != 0.0f || touchy != 0.0f) {
			float glowoff = (touchx < 0.0) ? -1.0f : 0.0f;
			yrTexture glowtex = (touchx < 0.0) ? tpadbut_delete_glow : tpadbut_cancel_glow;
			yrRenderTrackedOverlay_draw(toolidx, glowtex, glowoff, -0.5f, glowoff + 1.0f, 0.5f, touchd ? 0xFFFF8010 : 0x80FF8010);
		}
		yrRenderTrackedOverlay_draw(toolidx, tpadbut_delete, -1.0f, -0.5f, 0.0f, 0.5f, 0xFFFFFFFF);
		yrRenderTrackedOverlay_draw(toolidx, tpadbut_cancel, 0.0f, -0.5f, 1.0f, 0.5f, 0xFFFFFFFF);
	}
	yrRenderTrackedOverlay_render(toolidx);

	if(selected) {
		//draw beam
		vec4i o = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, mat.col[3])));
		vec4f dir = vec4f_from_vec4i(vec4i_sub(beamdest, o));
		float dist = vec3f_length(dir);
		dir = vec4f_mul(1.0f/dist, dir);
		yrRender_beam(toolidx, mat.col[3], dir, selected->normal, dist / YR_ACCURACY, 0xFF2020C0);
		//handle press
		if(!touchdown && touchd) {
			if(touchx > 0.0f) {
				yrQuadStore_editlock(NULL);
				selected = NULL; //cancel
			} else {
				yrQuadStore_editlock(NULL);
				yrUndo_append(utRemove, selected, NULL, selected->ext->tiles, NULL);
				yrQuadStore_remove(selected);
				selected = NULL; //remove
			}
		}
	} else {
		if(!yrQuadStore_editlocked() && toucht) {
			vec4i o = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, mat.col[3])));
			tracehit h = yrInteraction_trace(o, vec4f_neg(mat.col[2]), DIST_MIN, DIST_MAX);
			vec4f n = h.q ? h.q->normal : mat.col[2];
			yrRender_beam(toolidx, mat.col[3], vec4f_neg(mat.col[2]), n, h.dist, 0xFF101060);
			if(!touchdown && touchd && h.q) {
				yrQuadStore_editlock(h.q); //select quad
				selected = h.q;
				beamdest = vec4i_add(h.q->v[1], h.q->v[2]);
				beamdest.m = _mm_srai_epi32(beamdest.m, 1); //divide by 2
			}
		}
	}
	touchdown = touchd;
}

static int delete_canfreeze(void)
{
	return selected == NULL;
}

static void	delete_forceidle(void)
{
	if(selected) {
		yrQuadStore_editlock(NULL);
		selected = NULL;
	}
}
