#include <../source/TAL/objbase.h>
#include <sys/types.h>
#include <direct.h>

vhandle_t	spline = LIBV_INVALID_HANDLE;

vec_t	V_LOCAL		c_speed		= 10;	/* s per sm */
vec_t	V_LOCAL		SPEED		= 2;	/* mm per minute */
vec_t	V_LOCAL		F_SPEED		= 100;	/* kg per sm */

/*
 *	Coordinates in mm
 */

#define	GET_DEF(coord)		((((coord) * c_speed / 10) * SPEED) / 60)

/*
#define	S_OVERRIDE	((vec_t)7.0f/450.0f)	// mm per mm
#define	GET_DEF(coord)		((coord) * S_OVERRIDE)
*/

#define	GET_FORCE(coord)	((coord) * 0.1f * F_SPEED)

vec_t V_LOCAL
str_to_float(char *str)
{
	char buf[64];
	char *ptr;
	strCopy(buf,str,64);
	for(ptr=buf;*ptr;ptr++)
		if(*ptr==',')
			*ptr=',';
	return (vec_t)atof(buf);
}

vboolean	V_LOCAL
construct_spline(char *infile)
{
	bstack_t pairs;
	vec_t pair[2];
	char *next;
	u32_t i;
	vector_t *vx, *vy;
	vhandle_t p = lexParseFile(infile,"\t");
	if(!p)
		return false;
	stackInit(&pairs,2*sizeof(vec_t));
	for(;;)
	{
		do {
			next=lexNext(p);
		} while(next && next[0]<=' ');
		if(!next)
			break;
		pair[0]=str_to_float(next);
		do {
			next=lexNext(p);
		} while(next && next[0]<=' ');
		if(!next)
			break;
		pair[1]=str_to_float(next);
		stackPush(&pairs,pair);
	}
	lexDestroy(p);
	i=stackCount(&pairs);
	conlPrintf(LOG_INFO,"construct_spline('%s'): read in %u pairs,\n",
		infile,i);
	vx=vecAlloc(i);
	vy=vecAlloc(i);
	for(i--;stackPop(&pairs,pair);i--)
	{
		vx->elements[i]=pair[0];
		vy->elements[i]=pair[1];
	}
	spline = cspCreate(vx,vy);
	memFree(vx);
	memFree(vy);
	stackClear(&pairs);
	return true;
}

vec_t V_LOCAL
correct_deformation(vec_t raw_def,vec_t force)
{
	vec_t dd;
	dd = cspInterpolate(spline,force);
	printf("deform(force=%g)=%g\n",force,dd);
	return raw_def-dd;
}

void	V_LOCAL	V_CALL
enum_proc(char *filename)
{
	vec_t pair[2];
	char *next;
	vhandle_t outfile;
	char name[_MAX_FNAME],ext[_MAX_EXT],outname[_MAX_PATH];
	int count;
	vhandle_t p;
	fsSplitPath(filename,NULL,name,ext);
	if(strcmp(ext,"in"))
	{
		conlPrintf(LOG_WARNING,
			"Unknown file type '%s' of '%s%s%s' (expected 'in'); ignored,\n",
			ext,name,ext[0] ? "," : "",ext);
		return;
	}
	p = lexParseFile(filename,"\t");
	if(!p)
	{
		conlPrintf(LOG_ERROR,"enum_proc('%s'): can't process file,\n",
			filename);
		return;
	}
	fsMakePath(outname,NULL,name,"csv");
	outfile = fileOpenWrite(outname);
	if(!outfile)
	{
		lexDestroy(p);
		return;
	}
	for(count=0;;count++)
	{
		do {
			next=lexNext(p);
		} while(next && next[0]<=' ');
		if(!next)
			break;
		pair[0]=GET_DEF(str_to_float(next));
		do {
			next=lexNext(p);
		} while(next && next[0]<=' ');
		if(!next)
			break;
		pair[1] = GET_FORCE(str_to_float(next));
		/* Correct deformation and write pair out */
		filePrintf(outfile,"%g;%g\n",
			correct_deformation(pair[0],pair[1]),pair[1]);
	}
	fileClose(outfile);
	lexDestroy(p);
	conlPrintf(LOG_INFO,"enum_proc(): wrote %d pairs to '%s',\n",
		count,outname);
	return;
}

int main(int argc,char *argv[])
{
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	conPuts("Corrector for raw diagrams produced by IR-5057 - type press,\n"
		"Copyright (C) Vladimir A, Smirnov, 2000, 2007.\n");
	if(argc!=6 || !strcmp(argv[1],"--help"))
	{
		conlPuts(LOG_ERROR,"Usage: rc sec_per_sm mm_per_minute kg_per_sm <calibration curve data> "
			"<input directory>\nWhere:\n"
			"<calibration curve data>: file with pairs in form '<float force, kg>\\t<float deform, mm>\\n'\n"
			"<input directory>: directory with *.in files with pairs in form:\n"
			"\t'<float deform coord, mm>\\t<float force coord, mm>\\n',\n");
		return -1;
	}
	c_speed = str_to_float(argv[1]);
	SPEED = str_to_float(argv[2]);
	F_SPEED = str_to_float(argv[3]);
	conPrintf("Parameters: %g seconds/sm, %g mm/min, %g kg/sm\n",
		c_speed,SPEED,F_SPEED);
	if(!construct_spline(argv[4]))
	{
		conlPrintf(LOG_ERROR,"Can't construct spline for calibration file '%s'\n,",
			argv[4]);
		return -1;
	}
	if(chdir(argv[5]))
	{
		conlPrintf(LOG_ERROR,"Can't read directory '%s'\n,",
			argv[5]);
		cspDestroy(spline);
		return -1;
	}
	/* Do it ! */
	fsEnumFiles(NULL,enum_proc,false);
	/* Clean up */
	cspDestroy(spline);
	return 0;
}
