/****************************************************************************
 *                                                                          *
 *     Loki - Programs for genetic analysis of complex traits using MCMC    *
 *                                                                          *
 *                     Simon Heath - CNG, Evry                              *
 *                                                                          *
 *                         January 2003                                     *
 *                                                                          *
 * merlin.c:                                                                *
 *                                                                          *
 * MERLIN/QTDT compatability routines                                       *
 *                                                                          *
 * Copyright (C) Simon C. Heath 2003                                        *
 * This is free software.  You can distribute it and/or modify it           *
 * under the terms of the Modified BSD license, see the file COPYING        *
 *                                                                          *
 ****************************************************************************/

#include <config.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <math.h>

#include "getopt.h"
#include "version.h"
#include "libhdr.h"
#include "ranlib.h"
#include "utils.h"
#include "scan.h"

#define BUFSIZE 512

int strip_vars;

char *skip_blank(char *s)
{
	while(*s && isspace((int)*s)) s++;
	return s;
}

char *skip_nonblank(char *s)
{
	while(*s && !isspace((int)*s)) s++;
	return s;
}

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "process_qtdt"
int process_qtdt(int argc,char *argv[],char **LogFile,int *error_check,loki_time *lt)
{
	static int noprune=0;
	int c,err,i,j,ncols=0,col_size=8,line,anon_var=0,nmark=0;
	FILE *fptr,*fin;
	char *datafile=0,*pedfile=0,*mapfile=0,*lfile=0,*missing=0,*p,*p1,*p2;
	static char buf[BUFSIZE];
	
	struct column {
		int c;
		char *name;
	} *cols=0;

	static struct option longopts[]={
		 {"noprune",no_argument,&noprune,1},
		 {"prune",no_argument,&noprune,0},
		 {"log",required_argument,0,'l'},
		 {0,0,0,0}
	};
	static char *fixed[]={
		  "Set skip_bad_ints 1\n",
		  "Set skip_bad_reals 1\n",
		  "Missing [\"RIF\"] \"x\"\n",
		  "Missing [\"RIF\"] \"X\"\n",
		  "Missing [\"F\"] \"0\"\n",
		  "Missing \"?\" sex_var\n",
		  "Pedigree family,id,father,mother\n",
		  "Sex sex_var \"1\",\"2\"\n",
		  "Sex sex_var \"M\",\"F\"\n",
		  "Sex sex_var \"m\",\"f\"\n",
		  0
	};
	
	while((c=getopt_long(argc,argv,"evm:d:p:x:l:X:",longopts,0))!=-1) switch(c) {
	 case 'e':
		error_check=0;
		break;
	 case 'v':
		print_version_and_exit();
		break; /* Previous command never returns */
	 case 'd':
		datafile=strdup(optarg);
		break;
	 case 'p':
		pedfile=strdup(optarg);
		break;
	 case 'm':
		mapfile=strdup(optarg);
		break;
	 case 'x':
		missing=strdup(optarg);
		break;
	 case 'l':
		lfile=strdup(optarg);
		break;
	 case 'X':
		fputs("-X option must occur as first argument\n",stderr);
		exit(EXIT_FAILURE);
	}
	if(!datafile) {
		fputs("No data file specified (use -d option)\n",stderr);
		exit(EXIT_FAILURE);
	}
	if(!pedfile) {
		fputs("No pedigree file specified (use -p option)\n",stderr);
		exit(EXIT_FAILURE);
	}
	/* Now we create a temporary command file which we can feed into the standard parse routines */
	if(!(fptr=tmpfile())) ABT_FUNC("Couldn't create temporary file\n");
	i=0;
	p=fixed[i];
	while(p) {
		(void)fputs(p,fptr);
		p=fixed[++i];
	}
	if(lfile) fprintf(fptr,"Log \"%s\"\n",lfile);
	else fputs("Log \"loki.log\"\n",fptr);
	if(missing) fprintf(fptr,"Missing [\"R\"] \"%s\"\n",missing);
	fprintf(fptr,"File [GS=' \\f\\r\\n\\t/'] \"%s\",family,id,father,mother,sex_var",pedfile);
	if(!(fin=fopen(datafile,"r"))) {
		perror("Couldn't open datafile for input");
		ABT_FUNC("Aborting\n");
	}
	if(!(cols=malloc(sizeof(struct column)*col_size))) ABT_FUNC(MMsg);
	line=0;
	while(fgets(buf,BUFSIZE,fin)) {
		line++;
		p=skip_blank(buf);
		p1=skip_nonblank(p);
		if(*p1) {
			*p1++=0;
			p1=skip_blank(p1);
			if(*p1) {
				p2=skip_nonblank(p1);
				*p2=0;
			}
		}
		if(*p) {
			if(!*p1) fprintf(stderr,"Line %d: Item type %c has no name\n",line,p[0]);
			c=toupper((int)p[0]);
			(void)fputc(',',fptr);
			switch(c) {
			 case 'M':
				nmark++;
			 case 'A':
			 case 'T':
			 case 'C':
				if(ncols==col_size) {
					col_size+=2;
					if(!(cols=realloc(cols,sizeof(struct column)*col_size))) ABT_FUNC(MMsg);
				}
				if(*p1) {
					if(!(cols[ncols].name=malloc(3+strlen(p1)))) ABT_FUNC(MMsg);
					sprintf(cols[ncols].name,"%s__",p1);
					strip_vars=1;
				} else {
					i=1+(int)(log((double)++anon_var)/log(10.0));
					if(!(cols[ncols].name=malloc((size_t)(i+5)))) ABT_FUNC(MMsg);
					sprintf(cols[ncols].name,"var_%d",anon_var);
				}
				fputs(cols[ncols].name,fptr);
				cols[ncols++].c=c;
				break;
			 case 'Z':
			 case 'S':
			 case 'E':
				break;
			 default:
				fprintf(stderr,"Line %d: error in datafile - unknown item type (%c)\n",line,c);
				ABT_FUNC("Aborting\n");
			}
			if(c=='E') break;
		}
	}
	fputc('\n',fptr);
	if(nmark) {
		fputs("Marker Loci",fptr);
		for(j=i=0;i<ncols;i++) if(cols[i].c=='M') {
			fputc(j++?',':' ',fptr);
			fputs(cols[i].name,fptr);
		}
		fputs("\nInteger",fptr);
		for(j=i=0;i<ncols;i++) if(cols[i].c=='M') {
			fputc(j++?',':' ',fptr);
			fputs(cols[i].name,fptr);
		}
		fputc('\n',fptr);
		if(!mapfile) {
			fputs("Link 'chr'",fptr);
			for(j=i=0;i<
				 ncols;i++) if(cols[i].c=='M') {
					 fputc(',',fptr);
					 fputs(cols[i].name,fptr);
				 }
			fputc('\n',fptr);
		}
	}
	for(i=0;i<ncols;i++) if(cols[i].c=='A') {
		p=cols[i].name;
		fprintf(fptr,"Discrete %s\n",p);
		fprintf(fptr,"Affected where (%s=='2' || %s=='D' || %s=='A' || %s=='Y')\n",p,p,p,p);
		fprintf(fptr,"Unaffected where (%s=='1' || %s=='U' || %s=='N')\n",p,p,p);
		break;
	}
	fclose(fin);
	fseek(fptr,0,SEEK_SET);
	init_stuff(LogFile);
	err=ReadControl(fptr,"<TMP FILE>",LogFile);
	(void)fclose(fptr);
	if(!err) {
		if(getseed("seedfile",0)) init_ranf(135421);
		RunID=(unsigned int)(ranf()*(double)0xffffffffU);
		print_start_time(PREP_NAME,"w",*LogFile,lt);
		if(!scan_error_n) ReadData(*LogFile);          /* Read in the datafile(s) and recode (where necessary) */
	}
	if(datafile) free(datafile);
	if(pedfile) free(pedfile);
	if(mapfile) free(mapfile);
	if(missing) free(missing);
	if(lfile) free(lfile);
	for(i=0;i<ncols;i++) free(cols[i].name);
	free(cols);
	return err;
}

