#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <malloc.h>

#include <parse.h>
#include "dm.h"
#include "dm_globals.h"

void print_ontology();

// method: read_task
//
// arguments:
//  char *dir: directory of task file
//  char *task_file: name of the task_file in said directory
//
// return: none
//
// uses global variables (num_forms, ontology)
// this function reads in the task file and puts the whole thing into
// the global ontology structure. It uses temp dynamically allocated structs
// which are then put into the global. See layout of task file to make more
// sense of each type.
//
void read_task(char *dir, char *task_file) {
  int   slot_num;
  int   fn;
  int   j;
  int   slot_per_frame;
  int   cnt;
  char	name[LINE_LEN];
  char	root[LINE_LEN];
  char	path[LINE_LEN];
  char	line[LINE_LEN];
  char	prompt[LINE_LEN];
  char	*r;
  char	*c;
  Slot	*form_buf;
  FILE	*fp;
    
  // open task file
  sprintf(line, "%s/%s", dir, task_file);
  if( !(fp = fopen(line, "r")) ) {
    fprintf(stderr, "ERROR: can't open %s in read_task()\n", line);
    exit(-1);
  }
  
  // count frames and slots_per_frame
  slot_per_frame= 0;
  slot_num = 0;
  for(num_forms = 0; ; num_forms++ ) {
    
    // scan for start of frame
    while( (r = fgets(line, LINE_LEN, fp)) ) {
      sscanf(line, "%s%*[^\n]\n", name);
      if( !scmp("Frame", name) ) break;
    }
    if( !r ) break;
    
    // count slot declarations
    slot_num= 0;
    while( (r= fgets(line, LINE_LEN, fp)) ) {
      if( sscanf(line, "%s%*[^\n]\n", name) < 1 )
	continue;
      if( name[0] == ';' )
	break;
      else if( name[0] == '[' )
	slot_num++;
      else if( name[0] == '.' )
	slot_num++;
    }
    if (!r) {
      fprintf(stderr, "Bad format in forms file\n");
      exit(-1);
    }
    if( slot_num > slot_per_frame )
      slot_per_frame = slot_num;
    
  }
  
  // malloc space for frame templates
  if( !(ontology = (aFrameDef *) calloc(num_forms, sizeof(aFrameDef)))) {
    fprintf(stderr, "ERROR: malloc Frame templates failed\n");
    exit(-1);
  }
  
  // malloc space for temporary slots buffer
  if( !(form_buf = (Slot *) calloc(slot_per_frame, sizeof(Slot))) ) {
    fprintf(stderr, "ERROR: malloc form buffer failed\n");
    exit(-1);
  }
  
  rewind(fp);
  // for each frame in file
  for(fn = 0; ; fn++ ) {
    
    // scan for start of frame
    while( (r = fgets(line, LINE_LEN, fp)) ) {
      sscanf(line, "%[^:]:%s", prompt, name);
      if( !scmp("Frame", prompt) ) break;
    }
    if (!r) break;
    // If does not match 'Frame'
    if (scmp("Frame", prompt) != 0)
      break;
    
    // copy frame name
    cp_str( &((ontology+fn)->name), name);
    
    // read slot names and prompts
    slot_num = -1;
    prompt[0] = 0;
    while ( (r = fgets(line, LINE_LEN, fp)) ) {
      //goto end of whitespace
      for (c = line; isspace( (int) *c); c++);
      //if end if string, continue
      if (!*c)
	continue;
      if (*c == ';')
	break;
      
      // new root net
      if (*c == '[') {
	prompt[0] = (char)0;
	if( sscanf(c, "%[^+* \n]%s", name, prompt) < 1)
	  continue;

	slot_num++;
	
	// copy key string into slot
	(form_buf+slot_num)->key = (char *)0;
	cp_str( &((form_buf+slot_num)->key), name);
	(form_buf+slot_num)->required = prompt[0];
	(form_buf+slot_num)->prompt = (char *)0;
	(form_buf+slot_num)->sql = (char *)0;
	(form_buf+slot_num)->conf_prompt = (char *)0;

	strcpy(root, name);
      }
      
      // new child net
      else if (*c == '.') {
	prompt[0] = (char)0;
	c++;
	if (sscanf(c, "%[^+*\n]%s", name, prompt) < 1)
	  continue;
	sprintf(path, "%s%s", root, name);
	slot_num++;
	
	// copy key string into slot
	(form_buf+slot_num)->key = (char *)0;
	cp_str( &((form_buf+slot_num)->key), path);
	(form_buf+slot_num)->required = prompt[0];
	(form_buf+slot_num)->prompt = (char *)0;
	(form_buf+slot_num)->sql = (char *)0;
	(form_buf+slot_num)->conf_prompt = (char *)0;
      }
      
      // prompt template
      else if (*c == 'P') {
	if( !(c= index(c, (int) '"')) )
	  continue;
	c++;
	prompt[0] = (char)0;
	
	while( 1 ) {
	  while( isspace( (int) *c) ) c++;
	  if( (cnt= sscanf(c, "%[^\"\n]", name)) < 1) break;
	  strcat(prompt,name);
	  if( (c = index(c, (int) '"')) ) break;
	  if( !(r = fgets(line, LINE_LEN, fp)) ) break;
	  c = line;
	}
	
	// copy prompt string into slot
	(form_buf+slot_num)->prompt= (char *)0;
	cp_str( &((form_buf+slot_num)->prompt), prompt);
      }
      
      // sql template
      else if( *c == 'S' ) {
	if( !(c= index(c, (int) '"')) ) continue;
	c++;
	prompt[0]= (char)0;
	while( 1 ) {
	  while( isspace( (int) *c) ) c++;
	  if( (cnt= sscanf(c, "%[^\"\n]", name)) < 1) break;
	  strcat(prompt,name);
	  if( (c= index(c, (int) '"')) ) break;
	  if( !(r= fgets(line, LINE_LEN, fp)) ) break;
	  c= line;
	}
	
	// copy sql string into slot
	(form_buf+slot_num)->sql= (char *)0;
	cp_str( &((form_buf+slot_num)->sql), prompt);
      }
      
      // confirm prompt template
      else if( *c == 'C' ) {
	if( !(c= index(c, (int) '"')) ) continue;
	c++;
	prompt[0]= (char)0;
	while( 1 ) {
	  while( isspace( (int) *c) ) c++;
	  if( (cnt= sscanf(c, "%[^\"\n]", name)) < 1) break;
	  strcat(prompt,name);
	  if( (c= index(c, (int) '"')) ) break;
	  if( !(r= fgets(line, LINE_LEN, fp)) ) break;
	  c= line;
	}
	
	// copy prompt string into slot
	(form_buf+slot_num)->conf_prompt= (char *)0;
	cp_str( &((form_buf+slot_num)->conf_prompt), prompt);
      }
      
    }
    if (!r) {
      fprintf(stderr, "Bad format in forms file\n");
      exit(-1);
    }
    
    slot_num++;
    
    // copy to frame definition structure
    (ontology+fn)->n_slot= slot_num;
    
    // malloc space for slot array
    if( !( (ontology+fn)->slot= (Slot *)malloc(slot_num * sizeof(Slot)))){
      fprintf(stderr, "ERROR: malloc form def failed\n");
      exit(-1);
    }
    
    // copy temporary structure
    for(j = 0; j < slot_num; j++) {
      (ontology+fn)->slot[j] = form_buf[j];
    }
    
  }
  fclose(fp);
}

// method: print_ontology()
//
// arguments:
//  none
//
// return: none
//
// uses global variables (num_forms, ontology)
// this function prints out details about what has been read in from the task
// file
//
void print_ontology() {
  aFrameDef *fd;
  Slot *s;
  int j, fn;
  
  printf("Ontology: %d\n", num_forms);
  for(fn=0, fd= ontology; fn < num_forms; fn++, fd++ ) {
    printf("Frame: %s\n", fd->name);
    
    for(j=0, s= fd->slot; j < fd->n_slot; j++, s++) {
      printf("\tKey: %s\n", s->key);
      if( s->prompt ) printf("\tPrompt: %s\n", s->prompt);
      if( s->sql ) printf("\tSql: %s\n", s->sql);
      if( s->required ) printf("\tRequired: %c\n", s->required);
      else printf("\tRequired: 0\n");
      fflush(stdout);
    }
  }
  fflush(stdout);
}

