/**********************************************************************
	"Copyright 1990-2026 Brian MacWhinney. Use is subject to Gnu Public License
	as stated in the attached "gpl.txt" file."
*/

#include "ced.h"
#include "cu.h"
#ifdef _WIN32 
	#include "stdafx.h"
#endif

#if !defined(UNX)
#define _main temp_main
#define call temp_call
#define getflag temp_getflag
#define init temp_init
#define usage temp_usage
#endif

#include "mul.h" 

#define IS_WIN_MODE FALSE
#define CHAT_MODE 0

extern struct tier *defheadtier;
extern char OverWriteFile;
extern char isRecurive;

#define MAXREPEATS 20
struct rules {
	int index;
	float st[MAXREPEATS], et[MAXREPEATS];
	int  rule;
	char *text[MAXREPEATS];
	char *pho[MAXREPEATS];
	struct rules *nextRule;
} ;

#define MAXRULES 50
struct ages {
	char *age;
	struct rules *rules[MAXRULES];
	struct ages *nextAge;
} ;

struct sps {
	char *sp;
	struct ages *ageList;
	struct sps *nextSp;
} ;

struct sps *spList;

void init(char f) {
	if (f) {
		spList = NULL;
		OverWriteFile = TRUE;
		onlydata = 1;
		FilterTier = 0;
		LocalTierSelect = TRUE;
		if (defheadtier != NULL) {
			if (defheadtier->nexttier != NULL)
				free(defheadtier->nexttier);
			free(defheadtier);
			defheadtier = NULL;
		}
	}
	stout = TRUE;
}

void usage() {
	printf("Converts ACAD text files to CHAT text files\n");
	printf("Usage: temp [%s] filename(s)\n", mainflgs());
	cutt_exit(0);
}

CLAN_MAIN_RETURN main(int argc, char *argv[]) {
	isWinMode = IS_WIN_MODE;
	chatmode = CHAT_MODE;
	CLAN_PROG_NUM = TEMP;
	OnlydataLimit = 0;
	UttlineEqUtterance = TRUE;

	bmain(argc,argv,NULL);
}

void getflag(char *f, char *f1, int *i) {
	f++;
	switch(*f++) {
		case 'r':
			maingetflag(f-2,f1,i);
			break;
		default:
			fprintf(stderr,"Invalid option: %s\n", f-2);
			cutt_exit(0);
			break;
	}
}

static void freeRules(struct rules *p) {
	int i;
	struct rules *t;

	while (p != NULL) {
		t = p;
		p = p->nextRule;
		for (i=0; i < t->index; i++) {
			if (t->text[i] != NULL)
				free(t->text[i]);
			if (t->pho[i] != NULL)
				free(t->pho[i]);
		}
		free(t);
	}
}

static void freeAgeList(struct ages *p) {
	int r;
	struct ages *t;

	while (p != NULL) {
		t = p;
		p = p->nextAge;
		if (t->age != NULL)
			free(t->age);
		for (r=0; r < MAXRULES; r++) {
			if (t->rules[r] != NULL) {
				freeRules(t->rules[r]);
			}
		}
		free(t);
	}
}

static void freeSpList(struct sps *p) {
	struct sps *t;

	while (p != NULL) {
		t = p;
		p = p->nextSp;
		if (t->sp != NULL)
			free(t->sp);
		freeAgeList(t->ageList);
		free(t);
	}
}

static void memoryError(const char *err) {
	fprintf(stderr,"\n*** File \"%s\": ", oldfname);
	fprintf(stderr,"line %ld.\n", lineno);
	fprintf(stderr, err);
	freeSpList(spList);
	cutt_exit(0);
}

static void addtextPho(struct rules *p, float st, float et, char *text, char *pho) {
	if (p->index < MAXREPEATS-1) {
		if ((p->text[p->index]=(char *)malloc(strlen(text)+1)) == NULL) 
			memoryError("ERROR: out of memory.\n");
		p->st[p->index] = st;
		p->et[p->index] = et;
		strcpy(p->text[p->index], text);
		
		if ((p->pho[p->index]=(char *)malloc(strlen(pho)+1)) == NULL) 
			memoryError("ERROR: out of memory.\n");
		strcpy(p->pho[p->index], pho);
		p->index++;
	} else {
		strcpy(spareTier1, "Internal error exceeded max number of rules for the same speaker and age: 20\n");
		memoryError(spareTier1);
	}
}

static void addToRulesList(struct ages *age, float st, float et, int rule, char *text, char *pho) {
	if (age->rules[rule] == NULL) {
		age->rules[rule] = NEW(struct rules);
		if (age->rules[rule] == NULL)
			memoryError("ERROR: out of memory.\n");
		age->rules[rule]->rule = rule;
		age->rules[rule]->index = 0;
		addtextPho(age->rules[rule], st, et, text, pho);
	} else {
		addtextPho(age->rules[rule], st, et, text, pho);
	}
}

static struct ages *addToAgeList(struct ages *ageList, float st, float et, char *age, int rule, char *text, char *pho) {
	int i;
	struct ages *p;

	if (ageList == NULL) {
		p = NEW(struct ages);
		ageList = p;
	} else {
		for (p=ageList; p->nextAge != NULL; p=p->nextAge) {
			if (uS.mStricmp(p->age, age) == 0) {
				addToRulesList(p, st, et, rule, text, pho);
				return(ageList);
			}
		}
		if (uS.mStricmp(p->age, age) == 0) {
			addToRulesList(p, st, et, rule, text, pho);
			return(ageList);
		}
		p->nextAge = NEW(struct ages);
		p = p->nextAge;
	}
	if (p == NULL)
		memoryError("ERROR: out of memory.\n");
	if ((p->age=(char *)malloc(strlen(age)+1)) == NULL) 
		memoryError("ERROR: out of memory.\n");
	strcpy(p->age, age);
	for (i=0; i < MAXRULES; i++)
		p->rules[i] = NULL;
	if (rule < 0 || rule > MAXRULES) {
		sprintf(spareTier1, "ERROR: Current rule # of %d is greater than max # of %d\n", rule, MAXRULES);
		memoryError(spareTier1);
	}
	addToRulesList(p, st, et, rule, text, pho);
	return(ageList);
}

static struct sps *addToSpList(struct sps *spList, float st, float et, char *sp, char *age, int rule, char *text, char *pho) {
	struct sps *p;

	if (spList == NULL) {
		p = NEW(struct sps);
		spList = p;
	} else {
		for (p=spList; p->nextSp != NULL; p=p->nextSp) {
			if (uS.mStricmp(p->sp, sp) == 0) {
				p->ageList = addToAgeList(p->ageList, st, et, age, rule, text, pho);
				return(spList);
			}
		}
		if (uS.mStricmp(p->sp, sp) == 0) {
			p->ageList = addToAgeList(p->ageList, st, et, age, rule, text, pho);
			return(spList);
		}
		p->nextSp = NEW(struct sps);
		p = p->nextSp;
	}
	if (p == NULL)
		memoryError("ERROR: out of memory.\n");
	if ((p->sp=(char *)malloc(strlen(sp)+1)) == NULL) 
		memoryError("ERROR: out of memory.\n");
	strcpy(p->sp, sp);
	p->ageList = addToAgeList(NULL, st, et, age, rule, text, pho);
	return(spList);
}

static void output(struct sps *spList) {
	int i, r, fi, year, month;
	char *m, *g;
	long beg, end;
	FNType mDirPathName[FNSize];
	struct sps *p;
	struct ages *a;
	FILE *fp;

	for (p=spList; p != NULL; p=p->nextSp) {
//		fprintf(stderr, "sp=%s\n", p->sp);
		strcpy(mDirPathName, wd_dir);
		addFilename2Path(mDirPathName, p->sp);
		if (access(mDirPathName, 0)) {
			if (my_mkdir(mDirPathName, S_IRWXU|S_IRGRP|S_IROTH)) {
				strcpy(spareTier1, "ERROR: Can't create folder: ");
				strcat(spareTier1, mDirPathName);
				strcat(spareTier1, "\n");
				memoryError(spareTier1);
			}
		}
		fi = strlen(mDirPathName);
		for (a=p->ageList; a != NULL; a=a->nextAge) {
//			fprintf(stderr, "    age=%s\n",a->age);
			addFilename2Path(mDirPathName, a->age);
			strcat(mDirPathName, ".cha");
			fp = fopen(mDirPathName, "w");
			if (fp == NULL) {
				strcpy(spareTier1, "ERROR: Can't create file: ");
				strcat(spareTier1, mDirPathName);
				strcat(spareTier1, "\n");
				memoryError(spareTier1);
			}
			fprintf(fp, "@Begin\n");
			fprintf(fp, "@Languages:	eng\n");
			fprintf(fp, "@Participants:	CHI Target_Child\n");
			year = atoi(a->age);
			m = strchr(a->age, '_');
			if (m != NULL)
				month = atoi(m+1);
			else
				month = 0;
			g = strchr(p->sp, '_');
			fprintf(fp, "@ID:	eng|ACAD|CHI|%d;%s%d.|%s|||Target_Child|||\n",
					year,((month<10)?"0":""),month,((g[1]=='F')?"female":"male"));
 			fprintf(fp, "@Media:	%s, audio\n", a->age);
			for (r=0; r < MAXRULES; r++) {
				if (a->rules[r] != NULL) {
					fprintf(fp, "@G:\tR%d\n",a->rules[r]->rule);
					for (i=0; i < a->rules[r]->index; i++) {
						beg = a->rules[r]->st[i];
						end = a->rules[r]->et[i];
						sprintf(templineC3, "%c%ld_%ld%c", HIDEN_C, beg, end, HIDEN_C);
						fprintf(fp, "*CHI:\t%s. %s\n", a->rules[r]->text[i], templineC3);
						fprintf(fp, "%%pho:\t%s\n", a->rules[r]->pho[i]);
					}
				}
			}
			fprintf(fp, "@End\n");
			fclose(fp);
			mDirPathName[fi] = EOS;
		}
	}
}

/*
 unichar bufU[2];
 char buf[10];
 NSRange aRange;
 NSString *str;
 
 str = [NSString stringWithUTF8String:"\u02a4"];
 strcpy(buf, [str UTF8String]);
 aRange.location = 0;
 aRange.length = 1;
 [str getCharacters:bufU range:aRange];
 fprintf(stdout, "%s; %d; %x\n", buf, bufU[0], bufU[0]);
*/
void call() {
	int i, j, rule;
	float st, et;
	char pho[BUFSIZ+2], text[BUFSIZ+2], sp[32], age[32];
	char unic[7];
	unichar num[2];

	num[1] = 0;
	unic[0] = '0';
	unic[1] = 'x';
	while (fgets_ced(templineC, UTTLINELEN, fpin, NULL)) {
		lineno++;
		pho[0] = EOS;
		text[0] = EOS;
		sp[0] = EOS;
		age[0] = EOS;
		rule = 0;
		i = 0;
		while (templineC[i] != EOS) {
			if (uS.partcmp(templineC+i, "\"start_seconds\":", FALSE, TRUE)) {
				i += 16;
				st = atof(templineC+i);
				st = st * 1000.0000;
			} else if (uS.partcmp(templineC+i, "\"end_seconds\":", FALSE, TRUE)) {
				i += 14;
				et = atof(templineC+i);
				et = et * 1000.0000;
			} else if (uS.partcmp(templineC+i, "\"phonetic_text\":", FALSE, TRUE)) {
				i += 16;
				if (templineC[i] == '"')
					i++;
				j = 0;
				while (templineC[i] != '"') {
					if (templineC[i] =='\\' && templineC[i+1] =='u') {
						strncpy(unic+2, templineC+i+2, 4);// CA A4
						unic[6] = EOS;
						num[0] = strtol(unic, NULL, 16);
						pho[j] = EOS;
						u_strcpy(pho+j, num, BUFSIZ);
						j = strlen(pho);
						i += 6;
					} else
						pho[j++] = templineC[i++];
				}
				pho[j] = EOS;
			} else if (uS.partcmp(templineC+i, "\"orthographic_text\":", FALSE, TRUE)) {
				i += 20;
				if (templineC[i] == '"')
					i++;
				j = 0;
				while (templineC[i] != '"') {
					text[j++] = templineC[i++];
				}
				text[j] = EOS;
			} else if (uS.partcmp(templineC+i, "\"raw_filename\":", FALSE, TRUE)) {
				i += 15;
				if (templineC[i] == '"')
					i++;
				i += 4;

				j = 0;
				while (templineC[i] != 'M' && templineC[i] != 'F' && templineC[i] != '"') {
					sp[j++] = templineC[i++];
				}
				if (templineC[i] != '"')
					sp[j++] = templineC[i++];
				sp[j] = EOS;
				if (templineC[i] == '_')
					i++;

				j = 0;
				while (isdigit(templineC[i]) || templineC[i] == 'M' || templineC[i] == 'Y' || templineC[i] == '_') {
					age[j++] = templineC[i++];
				}
				if (j > 0 && age[j-1] == '_')
					j--;
				age[j] = EOS;

				if (templineC[i] == 'R')
					i++;
				while (!isdigit(templineC[i]) && templineC[i] != '"')
					i++;
				rule = atoi(templineC+i);
			} else
				i++;
		}
//if (strcmp(sp, "10_M") == 0 && strcmp(age, "4Y_6M") == 0 && strcmp(rule, "R16") == 0)
//	j = 0;
		spList = addToSpList(spList, st, et, sp, age, rule, text, pho);
	}
	output(spList);
	freeSpList(spList);
}
