#include "main.h"
#include "quadexport.h"
#include "scenefile.h"
#include "vecmath.h"
#include "system.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

char*	narrow(const wchar_t* str);
int yr_appmain(void* appparam) {return -1;}
int wmain(int argc, wchar_t** argv)
{
	char* import_file	= (argc>=2) ? narrow(argv[1]) : NULL;
	char* scene			= (argc>=3) ? narrow(argv[2]) : NULL;
	if(argc > 3) {
		printf("Too many arguments.\n");
		free(import_file);
		import_file = NULL;
	}

	int err = 0;
	if(import_file) {
		if(!scene) {
			printf("Please specify a scene file as second argument.");
			err = -1;
		} else {
			err = yrQuadImport_multi(scene, import_file);
			if(err) printf("An error occured while processing '%s'.", import_file);
		}
	}
	else {
		wprintf(L"Usage: %s [import definition file] [ysf scene file]\n\n", argv[0]);
		printf("Import definition file format:\n------------------------------\n");
		printf("Every line defines a whiteboard to be imported by specifying its properties in the format [property]=[value]."
			   "Unknown properties and extra data on a line are ignored. Invalid or missing properties will be set to a default value.\n");
		printf("List of properties:\n"
			   "px=0.000\tX-coordinate of the lower left corner of the whiteboard\n"
			   "py=0.000\tY-coordinate of the lower left corner of the whiteboard\n"
			   "pz=0.000\tZ-coordinate of the lower left corner of the whiteboard\n"
			   "e0x=0.000\tX-offset of the lower right corner relative to the lower left\n"
			   "e0y=1.000\tY-offset of the lower right corner relative to the lower left\n"
			   "e0z=1.000\tZ-offset of the lower right corner relative to the lower left\n"
			   "e1x=0.000\tX-offset of the top left corner\n"
			   "e1y=1.000\tY-offset of the top left corner\n"
			   "e1z=1.000\tZ-offset of the top left corner\n"
			   "clr=#FFFFFF\tWhiteboard background color\n"
			   "img=\"\"\t\tPath to whiteboard content image\n"
			   "il=0.0\t\tDistance beween the left edge and the content image\n"
			   "ir=0.0\t\tDistance beween the right edge and the content image\n"
			   "it=0.0\t\tDistance beween the top edge and the content image\n"
			   "ib=0.0\t\tDistance beween the bottom edge and the content image\n");
	}

	free(import_file);
	free(scene);
	return err;
}

//missing functions
void _yrLogInternal(int level, uint32_t color, uint64_t duration, const char* file, int line, const char* function, const char* format, ...)
{
	if(level > 1) return;
	va_list args;
	va_start(args, format);
	vprintf(format, args);
	printf("\n");
	va_end(args);
}
vec4i yrVR_cold_get_coord_offset(yrSceneFile* sf)
{
	vec4i out = {{0,0,0,0}};
	return out;
}
vec4i	yrVR_get_coord_offset(void)
{
	vec4i out = {{0,0,0,0}};
	return out;
}
mat4f	yrVR_world_from_tracked(uint32_t idx)
{
	mat4f out = {{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}};
	return out;
}
unsigned char yrRender_bg_from_id(uint32_t id) { return 250; }
uint32_t yrRender_bg_to_id(unsigned char idx) {return 0;}
void yrSystem_register(enum yrSysId id,
					   yrSystem_init_func init,
					   yrSystem_tick_func tick,
					   yrSystem_save_func save,
					   yrSystem_canfreeze_func canfreeze,
					   yrSystem_freeze_func freeze,
					   yrSystem_unfreeze_func unfreeze,
					   yrSystem_shutdown_func shutdown,
					   unsigned int dependencies)
{;}
size_t	yrSystem_visible_quads(void) {return 8192;}

int yrSystem_seeksys(yrReadHandle* rh, enum yrSysId sys)
{
	int err = 0;
	size_t rw;
	int64_t sysoff;
	err = yrSFRead_seek(rh, sys * 8, 0);	if(err) return err;
	rw  = yrSFRead_read(rh, 8, &sysoff);	if(rw != 8) return -1;
	err = yrSFRead_seek(rh, sysoff, 0);		if(err) return err;
	return 0;
}

static int64_t			save_sysptr[sys_end] = {0};
int yrSystem_initinsert(yrSceneFile* sf, yrReadHandle** rh, yrWriteHandle** wh, enum yrSysId sys)
{
	size_t rw, pre;
	const size_t spsize = sizeof(save_sysptr);

	*wh = yrSFWrite_start(sf, spsize);					if(!*wh) goto onerror;
	*rh = yrSFRead_start(sf);							if(!*rh) goto onerror;
	rw  = yrSFRead_read(*rh, spsize, &save_sysptr);		if(rw != spsize) goto onerror;
	pre = save_sysptr[sys] - spsize;
	rw = yrSFWrite_copy(*wh, *rh, pre);					if(rw != pre) goto onerror;
	return 0;
onerror:
	if(*rh) yrSFRead_end(*rh);
	if(*wh) yrSFWrite_abort(*wh);
	*rh = NULL;
	*wh = NULL;
	return -1;
}

int yrSystem_endinsert(yrReadHandle* rh, yrWriteHandle* wh, enum yrSysId sys)
{
	int64_t pos, adjust, foo;
	//get offset
	pos = yrSFWrite_getptr(wh);
	//find system right after sys in the stream
	foo = INT64_MAX;
	for(size_t i = 0; i < sys_end; i += 1)
		if(save_sysptr[i] > save_sysptr[sys] && save_sysptr[i] < foo)
			foo = save_sysptr[i];
	adjust = pos - foo;
	//update ptr table
	for(size_t i = 0; i < sys_end; i += 1)
		if(save_sysptr[i] > save_sysptr[sys])
			save_sysptr[i] += adjust;	
	//copy rest of stream
	yrSFWrite_copy(wh, rh, INT64_MAX);
	//close handles
	yrSFRead_end(rh);
	return yrSFWrite_end(wh, save_sysptr);
}

void yrSystem_abortinsert(yrReadHandle* rh, yrWriteHandle* wh)
{
	yrSFRead_end(rh);
	yrSFWrite_abort(wh);
}
