// file: $isip/util/demo/isip_comm_server_dialog_manager/isip_comm_dialog_manager_task.cc
// version: $Id: isip_comm_dialog_navigation_mgr_task.cc 10113 2005-05-20 20:44:46Z elliott $
//

/*-----------------------------------------------------------------------*
 *                                                                       *
 *		CSLR Communicator Dialogue Manager 			 * 
 *		Task Specific Speech Act Functions 			 * 
 *                                                                       *
 *                                                                       *
 *   Wayne Ward (whw@cslr.colorado.edu)                              	 *
 *   Center for Spoken Language Research				 *
 *   University of Colorado at Boulder					 *
 *   (c) 1999 All Rights Reserved					 *
 *                                                                       *
 *-----------------------------------------------------------------------*/

#include "isip_comm_dialog_navigation_mgr.h"

// These are all turned into check_query_generic
//char *check_query_generic( aFrame **rframe, char *query_name);
//
//char *check_query_address( aFrame **rframe);
//char *check_query_list( aFrame **rframe);
//char *check_query_direction( aFrame **rframe);
//char *check_query_building( aFrame **rframe);
//char *check_query_distance( aFrame **rframe);
//char *check_query_bus( aFrame **rframe);
//char *check_query_intersect( aFrame **rframe);


/*-----------------------------------------------------------------------*
 *  Action Switch after integrating new input
 *-----------------------------------------------------------------------*/
// returns 0 if sent query to the database
// returns 1 if it did not a query
//
int action_switch(void *server_data) {
  aFrame  *frame = (aFrame *)0;
  int     i;
  
  printf("Entering action_switch\n");
  print_context(context);
  fflush(stdout);
  
  printf("====action_switch======context frames\n");
  for(i = 0;  i < MAX_FRAME_STACK; i++) {
    if( !context[i] )
      break;
    frame = context[i];
    print_frame(frame);
  }    
  printf("===============context frames==========end====\n");
  fflush(stdout);
  frame = (aFrame *)0;
  
  //******** General Actions **************
  printf("Entering general_actions\n");
  fflush(stdout);
  
  // if done,  say bye and end conversation
  /*  if (hangup) {
      #if MAJOR_DEBUG
      printf("entered hangup\n"); fflush(stdout);
      #endif
      set_prompted((aFrame *)0, (char *)0, (char *)0);
      prompt = "GOODBYE.";
      nl_request("prompt_user", prompt, NULL, 0, server_data, (char *)0);
      hangup_phone(server_data);
      return;
      }
  */
  
  // start over 
  if ( task && !scmp(task, "reset") ) {
#if MAJOR_DEBUG
    printf("entered start over\n"); fflush(stdout);
#endif
    task = (char *)0;
    reset_dm();
    reset_task();
    prompt = "How may I help you ?";
    set_prompted( (aFrame *)0, "[start]", (char *)0);
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    action = "prompt";
    return 1;
  }
  
  // repeat last output 
  if (action && !scmp("repeat", action) ) {
#if MAJOR_DEBUG
    printf("entered repeat\n"); fflush(stdout);
#endif
    nl_request("repeat", NULL, NULL, 1, server_data, (char *)0);
    return 1;
  }
  
  // check for clarification or error prompt 
  if (prompt) {
#if MAJOR_DEBUG
    printf("entered prompt\n"); fflush(stdout);
#endif
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    printf("exiting action switch from the prompt\n");
    return 1;
  }
  
  // clear old prompt 
  prompt = (char *)0;
  set_prompted((aFrame *)0, (char *)0, (char *)0);
  
  /******** Domain Actions **************/
  printf("entering domain actions\n");
  fflush(stdout);
  
  // if no active content frames 
  if( !getActiveFrame() ) {
#if MAJOR_DEBUG
    printf("entered !getActiveFrame\n"); fflush(stdout);
#endif
    prompt = "Where would you like to go";
    set_prompted( (aFrame *)0, "[start]", (char *)0);
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    return 1;
  }
  
  // if retry db query because of timeout 
  if( retry && save_task ) {
#if MAJOR_DEBUG
    printf("retry and save\n"); fflush(stdout);
#endif
    retry = 0;
    retry_query(server_data);
    task = save_task;
    action = "data";
    prompted= save_prompted;
    return 1;
  }
  
  // respond to specific question 
  if (*query_key) {
#if MAJOR_DEBUG
    printf("query_key [%s]\n", query_key); fflush(stdout);
#endif
    if( (row_in_focus >=0) && (db_rows >0) ) {
      nl_request("inquiry", query_key, task, 1, server_data, (char *)0);
      set_prompted(focus, "[accept]", "yes");
      *query_key = 0;
      action = "data";
      return 1;
    }
    query_key[0] = (char)0;
    prompt = "you must supply more information before I can answer that";
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    return 1;
  }
  
  // if change db row in focus 
  if( row_abs || row_rel ) {
    printf("ENTERED CODE I DIDN'T THINK WE WOULD\n");
    fprintf(stderr,"ENTERED CODE I DIDN'T THINK WE WOULD\n");
#if MAJOR_DEBUG
    printf("row_abs or row_rel\n"); fflush(stdout);
#endif
    if( data_current && (db_rows > 0) ) {
      if (row_abs)
	row_in_focus = row_abs-1;
      else
	row_in_focus++;
      
      focus = data_current;

      prompt = "I'm sorry, I didn't understand.";
      nl_request("prompt_user", prompt,
		 task, 1, server_data, (char *)0);

      set_prompted( focus, "[accept]", "yes");
      
      row_abs = 0;
      row_rel = 0;
      
      return 1;
    }
    row_abs = 0;
    row_rel = 0;
  }
  
  
  // if data to output 
  if( data_current && (db_rows > 0) ) {
    //fprintf(stderr,"ENTERED CODE I DIDN'T THINK WE WOULD\n");
    //printf("ENTERED CODE I DIDN'T THINK WE WOULD\n");
#if MAJOR_DEBUG
    printf("data to output\n"); fflush(stdout);
#endif
    focus = data_current;
    printf("about to set selection\n"); fflush(stdout);
    one_row = set_selection(focus, row_in_focus);
    printf("ending set selection\n"); fflush(stdout);

    prompt = "I'm sorry, I didn't understand.";
    nl_request("prompt_user", prompt,
	       task, 1, server_data, (char *)0);

    printf("done sending nl_request\n"); fflush(stdout);
    action = "data";
    set_prompted( focus, "[accept]", "yes");
    return 1;
  }
  
  // check focus first 
  if (focus != NULL) {
#if MAJOR_DEBUG
    printf("focus != null focus[%s]\n", focus->name); fflush(stdout);
#endif
    
    // check if "cityguide" frames complete and confirmed 
    /*
      if( !scmp(focus->name, "Cityguide") ) {
      if( (prompt= check_cityguide(&frame)) ) {
      nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
      prompt= (char *)0;
      action= "prompt";
      return;
      }
      }
    */
    
    // check if "Query_Address" frames complete and confirmed 
    if (!scmp(focus->name, "Query_Address") ) {
      //if( (prompt = check_query_address(&frame)) ) {
      if( (prompt = check_query_generic(&frame,"Query_Address")) ) {	  
	nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
	prompt = (char *)0;
	action = "prompt";
	
	// change the prompted frame to be "Query_Address" 
	prompted.frame = drive_frame;
	return 1;
      }
    }
    
    // check if "Query_List" frames complete and confirmed 
    if (!scmp(focus->name, "Query_List") ) {
      //if( (prompt = check_query_list(&frame)) ) {
      if( (prompt = check_query_generic(&frame,"Query_List")) ) {
	nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
	prompt = (char *)0;
	action = "prompt";
	
	// change the prompted frame to be "Query_List" 
	prompted.frame = drive_frame;
	return 1;
      }
    }
    
    // check if "Query_Direction" frames complete and confirmed 
    if (!scmp(focus->name, "Query_Direction") ) {
      //if( (prompt = check_query_direction(&frame)) ) {
      if( (prompt = check_query_generic(&frame,"Query_Direction")) ) {
	nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
	prompt = (char *)0;
	action = "prompt";
	
	// change the prompted frame to be "Query_Direction" 
	prompted.frame = drive_frame;
	return 1;
      }
    }
    
    // check if "Query_Distance" frames complete and confirmed 
    if (!scmp(focus->name, "Query_Distance") ) {
      //if( (prompt = check_query_distance(&frame)) ) {
      if( (prompt = check_query_generic(&frame,"Query_Distance")) ) {
	nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
	prompt = (char *)0;
	action = "prompt";
	
	// change the prompted frame to be "Query_Distance" 
	prompted.frame = drive_frame;
	return 1;
      }
    }
    
    
    // check if "Query_Building" frames complete and confirmed 
    if (!scmp(focus->name, "Query_Building") ) {
      //if( (prompt = check_query_building(&frame)) ) {
      if( (prompt = check_query_generic(&frame,"Query_Building")) ) {
	nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
	prompt = (char *)0;
	action = "prompt";
	
	// change the prompted frame to be "Query_Building" 
	prompted.frame = drive_frame;
	return 1;
      }
    }
    
    /*
    // This section is a prototype for the layout of
    // Query_Intersect and Query_Bus
    // check if "Query_Intersect" frames complete and confirmed 
    if (!scmp(focus->name, "Query_Intersect") ) {
    if( (prompt = check_query_generic(&frame,"Query_Intersect")) ) {
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    
    // change the prompted frame to be "Query_Intersect" 
    prompted.frame = drive_frame;
    return;
    }
    }
    
    // check if "Query_Bus" frames complete and confirmed 
    if (!scmp(focus->name, "Query_Bus") ) {
    if( (prompt = check_query_generic(&frame,"Query_Bus")) ) {
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    
    // change the prompted frame to be "Query_Bus" 
    prompted.frame = drive_frame;
    return;
    }
    }
    */
    
    // Check if "Query_WhereAmI" frames complete and confirmed 
    /*
    // Not complete enough for its own section
    //
    if (!scmp(focus->name, "Query_WhereAmI") ) {
    // This needs changing .. VVVV .. if this section is ever written
    if( (prompt= check_query_building(&frame)) ) {
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    // change the prompted frame to be "Query_WhereAmI"
    prompted.frame = drive_frame;
    return;
    }
    }
    */
    
    // check if "Query_General" frames complete and confirmed 
    if (!scmp(focus->name, "Query_General") ) {
      if( (prompt = check_drive(&frame)) ) {
	nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
	prompt = (char *)0;
	action = "prompt";
	return 1;
      }
    }
  } // end of (focus != NULL)
    // if focus was null, then "frame" is null right now too
  
    // if frame completed but not accepted, build dbq 
  if( frame && (getKeyPtr(frame, "[accept]")) ) {
#if MAJOR_DEBUG
    printf("frame && getKeyPtr\n"); fflush(stdout);
#endif
    data_current = frame;
    focus = frame;
    db_rows = 0;
    action = "data";
    set_prompted(frame, "[accept]", "yes");
           
    return build_dbq(db_buf, frame, server_data);
  }
  
  // check current frame for completion 
  if( focus && (prompt = frame_complete( focus) )) {
#if MAJOR_DEBUG
    printf("check frame for completion\n"); fflush(stdout);
#endif
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    return 1;
  }
  
  // prompt for unfilled slots in hotel and car frames
  //
  // This is different from above because the above is only the focus
  // and this is the entire frame
  //
  // If focus was null coming into this function, this this will find
  // a frame in context that is active and not completed
  //
  if( (prompt = complete_active_frames(&frame)) ) {
#if MAJOR_DEBUG
    printf("prompt = complete_active_frames\n"); fflush(stdout);
#endif
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    return 1;
  }
  
  // if frame completed but not accepted, build dbq 
  if( frame && (getKeyPtr(frame, "[accept]")) ) {
#if MAJOR_DEBUG
    printf("frame && [accept]\n"); fflush(stdout);
#endif
    data_current = frame;
    db_rows = 0;
    action = "data";
    set_prompted( frame, "[accept]", "yes");

    return build_dbq(db_buf, frame, server_data);    
  }
    
  // allow no changes if task finished 
  no_changes = 1;
  
  // if session done, log to hub at end of next utt 
  // This variable is left in here, but we don't use it anymore
  // because it was used back when 'notify_playing_has_ended' was used
  //
  session_done = 1;
  
  if( (prompt = frame_complete(focus)) ) {
#if MAJOR_DEBUG
    printf("prompt && frame complete\n"); fflush(stdout);
#endif
    nl_request("prompt_user", prompt, NULL, 1, server_data, (char *)0);
    prompt = (char *)0;
    action = "prompt";
    return 1;
  }
  
  // nothing else to do so say bye 
  /*
    hangup = 1;
    prompt = "THANKS FOR USING THE CU COMMUNICATOR.    GOODBYE.";
    nl_request("prompt_user", prompt, NULL, 0, server_data, (char *)0);
    hangup_phone(server_data);
  */
  
  printf("exited out end of function no problems\n"); fflush(stdout);
  return 1;
}


void reset_task() {
  
  // reset global variables 
  action = (char *)0;
  focus = (aFrame *)0;
  prompt_text[0] = (char)0;
  db_buf[0] = (char)0;
  
  nl_task = (char *)0;
  session_done = 0;
  session_done_logged = 0;
  data_current = (aFrame *)0;
  db_rows = 0;
  row_in_focus = -1;
  row_abs= row_rel = 0;
  //  backoff_cnt = 0;
  //  backoff_tried = 0;
  no_changes = 0;
  
  retry = 0;
  campus_depart = 0;
  campus_arrive = 0;
  save_task = (char *)0;
  save_sql = (char *)0;
  save_frame = (aFrame *)0;
  save_prompted.frame = (aFrame *)0;
  save_prompted.key = (char *)0;
  save_prompted.type = (char *)0;
  
  // reset drive_frame to NULL
  //
  drive_frame = (aFrame*)NULL;
  
  return;
}

// Uses global "task" and sets it to be the name of the task
void set_task(char *name) {
  if( !name ) return;
  
  if( !scmp("Query_Address", name) )         task = "Query_Address"; 
  else if( !scmp("Query_List", name) )       task = "Query_List"; 
  else if( !scmp("Query_Direction", name) )  task = "Query_Direction"; 
  else if( !scmp("Query_Distance", name) )   task = "Query_Distance"; 
  else if( !scmp("Query_Building", name) )   task = "Query_Building"; 
  else if( !scmp("Query_Bus", name) )        task = "Query_Bus";
  else if( !scmp("Query_Intersect", name) )  task = "Query_Intersect";
  else if( !scmp("Query_WhereAmI", name) )   task = "Query_WhereAmI";
  else {
    printf("ERROR: set_task() did not know what the type of task is!\n");
  }
}

void merge_context(aFrame **context, aFrame **extracts) {
  aFrame      *ef;
  aFrame      *cf;
  aFrame      *tmp_ef;
  char	      *dep;
  char        *arr;
  char 	      *val;
  int	      xx;
  int         i;
  
  // print extracted frames 
  if( dm_verbose > 1 ) {
    printf("begin extracted frames========\n");
    for(ef = getFrame(extracts, "*", "first", &xx); ef;
	ef = getFrame(extracts, "*", "next", &xx)) {
      print_frame(ef);
    }
    printf("end extracted frames=====\n");
    fflush(stdout);
  }
  
  // for each extracted frame 
  for(ef = getFrame(extracts, "*", "first", &xx); ef;
      ef = getFrame(extracts, "*", "next", &xx)) {
    
    printf("looking at extract frame = ");
    print_frame(ef);
    
    // if no changes, allow only "Closing" frame
    //if( no_changes && scmp("Closing", ef->name) != 0)
    // mwe-edit, We don't care about the Closing frame
    // so if there are no changes, don't allow any changes
    //
    if (no_changes)
      continue;
    
    // mwe-Removed entire section because we do not use the "Closing"
    // frame. It was the
    // Prompt:  "would you like a summary of your itinerary"
    // frame
    /*
    // [Return] frame
    if( !scmp("Return", ef->name)) {
    // find or create return frame
    if( !(cf= find_return()) ) {
    //create_return( (char *)0, (char *)0, (char *)0);
    //mwe-not sure if this focus matters so left in
    cf= focus;
    }
    // copy new values if not already accepted
    if( cmpVal(cf, "[accept]", "yes") )
    cp_key_values(cf, ef);
    continue;
    }
    */
    
    // if no appropriate frame in context, create one
    //
    if( !(cf = findContext(ef)) ) {
      
      printf("Looking at %s. did not find context Frame\n",ef->name);
      // if this is "Query_General" frame 
      if ( !scmp("Query_General", ef->name) ) {
	if( !(cf = createFrame(ef->name)) ) return;
	addFrame(context, cf);
	activateFrame(cf);
	setKey(cf, "[Depart_Loc].[City_Name]", (char *)"STARKVILLE");
	drive_frame = cf;
      }
      
      // if this is other query frame 
      else if ( !scmp("Query_Direction", ef->name) ||
		!scmp("Query_Distance", ef->name) || 
		!scmp("Query_Address", ef->name) || 
		!scmp("Query_List", ef->name) || 
		!scmp("Query_Building", ef->name) ) {
	if( !(cf= createFrame(ef->name)) )
	  return;
	addFrame(context, cf);
	activateFrame(cf);
	setKey(cf, "[Depart_Loc].[City_Name]", (char *)"STARKVILLE");
	
	// copy contexts from history frame
	//
	if (focus) {
	  // NOT-mwe.. why were these lines originally in here?
	  // (otherwords) i did not comment out the following two lines, 
	  // they were already commented out
	  // if (!scmp("Query_Direction", ef->name) ||
	  //  !scmp("Query_Distance", ef->name)) {
	  xcopy_frame(cf, focus);
	  //}
	}
	focus = cf;
	
	// if no "Query_General" frame in context, create one
	//
	if (drive_frame == NULL) {
	  drive_frame = createFrame("Query_General");
	  addFrame(context, drive_frame);
	  activateFrame(drive_frame);
	}
	
	// focus Query_General's frame to current query task
	//
	setKey(drive_frame, "[user_query]", ef->name);
	data_current = 0;
      } //end else if
      
      // this else will catch all other types of frames
      // and just create and add them. Good for Yes\No, etc frames
      else {
	if( !(cf = createFrame(ef->name)) )
	  return;
	addFrame(context, cf);
	activateFrame(cf);
      }
      
      setKey(cf,  "[Active]", "yes");
      
      mask_slots(cf, ef);
      cp_frame(cf, ef);
      
      // mwe-if there was no focus, set this to be focus
      // this results in a query_general or confirmation frame to
      // be active if no query_add, query_dir, etc exists
      if (focus == NULL) {
	focus = cf;
      }
      
      // according to current input, mask some slot if necessary 
      //	    mask_slots(cf, ef);
      
      if( data_current == cf ) 
	data_current = (aFrame *)0;
      
      continue;
    }
    printf("Have a context frame now for %s\n", ef->name);
    
    if ( !scmp("Query_General", ef->name) && 
	 (val = getVal(cf, "[user_query]")) ) {
      
      // switch this frame to the focused query task
      //
      if ( (tmp_ef = createFrame(val)) ) {
	xcopy_frame(tmp_ef, ef);
	//mwe-I'm not sure why this was commented out.
	//'ef' is a **Frame so it doesn't need to be erased here
	//	    freeFrame(ef);
	ef = tmp_ef;
	printf("mapped ef = ");
	print_frame(ef);
	fflush(stdout);
      }
    }
    
    dep = (char *)0;
    arr = (char *)0;
    cf = (aFrame *)0;
    
    // see if specific frame referenced by Depart City 
    //mwe-more than likely it will be the hardcoded "Starkville" above
    if( (val = getVal(ef, "[Depart_Loc].[City_Name]") ) ) {
      
      // if not prompted for and already in context
      if( scmp("[Depart_Loc]", prompted.key) != 0 &&
	  (cf = findFrame(ef->name, "[Depart_Loc].[City_Name]", val))) {
	// clear Depart_Loc key 
	setKey(ef,  "[Depart_Loc].[City_Name]", (char *)0);
      }
      else dep = val;
    }
    
    // see if specific frame referenced by Arrive City 
    if( !cf && (val = getVal(ef, "[Arrive_Loc].[City_Name]") ) ) {
      // if not prompted for  and already in context
      if( scmp("[Arrive_Loc]", prompted.key) &&
	  (cf = findFrame(ef->name, "[Arrive_Loc].[City_Name]", val))){
	// clear Arrive_Loc key 
	setKey(ef,  "[Arrive_Loc].[City_Name]", (char *)0);
      }
      else arr= val;
    }
    
    // if no frame specified, try current frame 
    if( !cf ) {
      if( !(cf = findContext(ef)) )
	continue;
      if(  !cmpVal(cf, "[confirmed]", "yes") && ( dep || arr ) &&
	   ( !scmp("[return]", prompted.key) ||
	     !scmp("[final]", prompted.key) ||
	     !scmp("[Arrive_Loc]", prompted.key)) ) {
	//mwe took out the line for inc_leg() since we dont use that
	//inc_leg();
	cf= focus;
      }
    }
    
    // don't change locations if frame confirmed 
    if(  !cmpVal(cf, "[confirmed]", "yes") ) {
      if( (val= getVal(ef, "[Depart_Loc].[City_Name]") ))
	setKey(ef,  "[Depart_Loc].[City_Name]", (char *)0);
      
      if( (val= getVal(ef, "[Arrive_Loc].[City_Name]") ))
	setKey(ef,  "[Arrive_Loc].[City_Name]", (char *)0);
    }
    
    // if empty frame 
    if( frame_empty(ef) )
      continue;
    
    // make frame active 
    setKey(cf, "[Active]", "yes");
    
    // if frame not accepted, cp values to current frame
    //
    if( cmpVal(cf, "[accept]", "yes") ) {
      // copy values to both special query frame
      //
      if ( !scmp("Query_Direction", ef->name) ||
	   !scmp("Query_Distance", ef->name) ||
	   !scmp("Query_Address", ef->name) ||
	   !scmp("Query_List", ef->name) ||
	   !scmp("Query_Building", ef->name) ) {
	
	// copy the context into current frame if switching task
	//
	if ( scmp(focus->name, ef->name) ) {
	  // mwe-again, NOT commented out by me, was already commented out
	  //if (!scmp("Query_Direction", ef->name) ||
	  //  !scmp("Query_Distance", ef->name)) {
	  xcopy_frame(cf, focus);
	  //}
	  
	  // also switch [Query_General]'s focus to current task
	  //
	  if( drive_frame != NULL) {
	    setKey(drive_frame, "[user_query]", ef->name);
	  }
	}
	
	// copy values
	//
	mask_slots(cf, ef);
	//mwe-begin debug
	printf("current [%x] extract [%x]\n",
	       (int)&(cf->name), (int)&(ef->name));
	printf("current [%s] extract [%s]\n", cf->name, ef->name);
	//printf("current [%s] extract [%s]\n", cf->name, ef->name);
	//mwe-end debug
	cp_frame(cf, ef);
	data_current = 0;
      }
      
      else {
	mask_slots(cf, ef);
	cp_values(cf, ef);
      }
      
      if ( getKeyPtr(cf, "[Active]") ) 
	focus = cf;
      
      // clear data flag 
      if( data_current == cf )
	data_current=0;
    }
    
    // if frame not active, activate 
    if (cmpVal(cf, "[Active]", "no") != 0) {
      setKey(cf, "[Active]", "yes");
      
    }
    
    // clear confirmed flag 
    if( (val= getVal(ef, "[Depart_Loc].[City_Name]") ) ||
	(val= getVal(ef, "[Arrive_Loc].[City_Name]") ) ||
	(val= getVal(ef, "[date_str]") ) ) {
      setKey(cf,  "[confirmed]", (char *)0);
    }
  }
  
  // move extracted frames to history list 
  cp_to_hist(extracts);
  
  // print history frames 
  if( dm_verbose > 1 ) {
    printf("history frames -- history index is %i\n", hist_idx);
    // Print all history frames from most recent to the oldest
    //
    for(i = hist_idx - 1;  i >= 0; i--) {
      if( !history[i] )
	break;
      ef = history[i];
      print_frame(ef);
    }
  }
}

// This function handles Query_General parses
char *check_drive( aFrame **rframe) {
  char	*prmpt;
  aFrame	*frame;
  int		xx;
  
  *rframe= (aFrame *)0;
  
  // if no Query_General frames 
  if(!(frame= getFrame(context, "Query_General", "first", &xx)) ) 
    return( (char *)0 );
  
  // set to first frame for optimize_price return 
  /* 1. optimize_distance
     2. optimize_price
  */
  //if( !scmp("optimize_distance", airmode) ) *rframe= frame;
  *rframe= frame;
  
  // if declined by user 
  if(  !cmpVal(frame, "[Active]", "no") )
    return( (char *)0 );
  
  // check if all Query_General frames complete 
  for(frame= getFrame(context, "Query_General", "first", &xx); frame;
      frame= getFrame(context, "Query_General", "next", &xx))
    {
      // if already accepted 
      if( !cmpVal(frame,"[accept]","yes")) {
	// if nine_best accepted, nothing to check 
	//( !scmp("optimize_price", airmode) ) {
	*rframe= (aFrame *)0;
	return( (char *)0 );
	//
	//else  continue;
      }
      
      // if frame not complete, prompt for missing info 
      if( (prmpt= frame_complete(frame)) ) {
	focus= frame;
	return(prmpt);
      }
      
      // ************** specially handle [user_query] 
      
      // if complete but not confirmed, then confirm 
      
      // if not nine_best, return to generate dbq 
      //if( scmp("optimize_distance", airmode) ) {
      *rframe= frame;
      return( (char *)0 );
      //}
    }
  return( (char *)0);
}

//mwe incase who ever wrote this didnt notice, everyone of these
//check_query_XXXX are the same except for a few lines that tell
//what type of query it is. Whynot just make a generic such as below?
char *check_query_generic( aFrame **rframe, char *query_name) {
  char	   *prmpt;
  aFrame   *frame;
  int	   xx;
  
  *rframe = (aFrame *)0;
  
  //make sure it is not a null string
  if (!query_name) {
    return( (char *)0 );
  }
  
  // if no query frames
  if(!(frame = getFrame(context, query_name, "first", &xx)) )
    return( (char *)0 );
  
  *rframe = frame;
  
  // if declined by user
  if(  !cmpVal(frame, "[Active]", "no") ) {
    return( (char *)0 );
  }
  
  // check if all "query_name" frames complete
  for(frame = getFrame(context, query_name, "first", &xx); frame;
      frame = getFrame(context, query_name, "next", &xx)) {
    
    // if already accepted
    if (!cmpVal(frame,"[accept]","yes")) {
      *rframe = (aFrame *)0;
      return (char *)0;
    }
    
    // if frame not complete, prompt for missing info
    if ((prmpt = frame_complete(frame))) {
      focus = frame;
      return prmpt;
    }

    // right now it only looks at the first "query_name" frame in context
    // and makes its decision based on that. I think there should only
    // ever be one frame but it doesn't make any sense to have a for(;;) loop
    // if there is only ever going to be one. It works though so I have other
    // things to work on.
    //
    *rframe = frame;
    return( (char *)0 );
  }

  // unreachable code
  return( (char *)0);
}


void mask_slots(aFrame *cf, aFrame *ef) {
  char *val;
  
  // Simple error checking
  //
  if (!cf || !ef)  return;
  
  // mask [Place_Type] etc if there is [Campus_Name] in *ef
  //
  if ( (val = getVal(ef, "[Arrive_Loc].[Place_Name]")) ) {
    
    setKey(ef, "[Arrive_Loc].[Place_Type]", 0);

    setKey(cf, "[Arrive_Loc].[Place_Type]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Spec]", 0);
    setKey(cf, "[Arrive_Loc].[Campus_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Address]", 0);
    setKey(cf, "[Arrive_Loc].[address]", 0);
    setKey(cf, "[Arrive_Loc].[Building_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Campus_Service_Name]", 0);
  }
  
  if ( (val = getVal(ef, "[Depart_Loc].[Place_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Depart_Loc].[Place_Type]", 0);

    setKey(cf, "[Depart_Loc].[Place_Type]", 0);
    setKey(cf, "[Depart_Loc].[Place_Spec]", 0);
    setKey(cf, "[Depart_Loc].[Campus_Name]", 0);
    setKey(cf, "[Depart_Loc].[Campus_Service_Name]", 0);
    setKey(cf, "[Depart_Loc].[Building_Name]", 0);
    setKey(cf, "[Depart_Loc].[Address]", 0);
    setKey(cf, "[Depart_Loc].[address]", 0);
  }
  
  // mask [Place_Type] etc if there is [Campus_Name] in *ef
  //
  if ( (val = getVal(ef, "[Arrive_Loc].[Campus_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Arrive_Loc].[Place_Type]", 0);

    setKey(cf, "[Arrive_Loc].[Place_Type]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Spec]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Building_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Campus_Service_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Address]", 0);
    setKey(cf, "[Arrive_Loc].[address]", 0);
    campus_arrive = 1;
  }
  
  // mask [Place_Type] etc. if there is [Building_Name] in *ef
  //
  if ( (val = getVal(ef, "[Arrive_Loc].[Building_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Arrive_Loc].[Place_Type]", 0);

    setKey(cf, "[Arrive_Loc].[Place_Type]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Spec]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Campus_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Campus_Service_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Address]", 0);
    setKey(cf, "[Arrive_Loc].[address]", 0);
    campus_arrive = 1;
  }
  
  // mask [Place_Type] etc. if there is [Campus_Service_Name] in *ef
  //
  if ( (val = getVal(ef, "[Arrive_Loc].[Campus_Service_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Arrive_Loc].[Place_Type]", 0);

    setKey(cf, "[Arrive_Loc].[Place_Type]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Spec]", 0);
    setKey(cf, "[Arrive_Loc].[Place_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Campus_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Building_Name]", 0);
    setKey(cf, "[Arrive_Loc].[Address]", 0);
    setKey(cf, "[Arrive_Loc].[address]", 0);
    campus_arrive = 1;
  }
  
  // mask [Place_Name] if there is [Campus_Name] in *ef
  //
  if ( (val = getVal(ef, "[Depart_Loc].[Campus_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Depart_Loc].[Place_Type]", 0);

    setKey(cf, "[Depart_Loc].[Place_Type]", 0);
    setKey(cf, "[Depart_Loc].[Place_Spec]", 0);
    setKey(cf, "[Depart_Loc].[Place_Name]", 0);
    setKey(cf, "[Depart_Loc].[Campus_Service_Name]", 0);
    setKey(cf, "[Depart_Loc].[Building_Name]", 0);
    setKey(cf, "[Depart_Loc].[Address]", 0);
    setKey(cf, "[Depart_Loc].[address]", 0);
    campus_depart = 1;
  }
  
  // mask [Place_Name] if there is [Campus_Name] in *ef
  //
  if ( (val = getVal(ef, "[Depart_Loc].[Building_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Depart_Loc].[Place_Type]", 0);

    setKey(cf, "[Depart_Loc].[Place_Type]", 0);
    setKey(cf, "[Depart_Loc].[Place_Spec]", 0);
    setKey(cf, "[Depart_Loc].[Place_Name]", 0);
    setKey(cf, "[Depart_Loc].[Campus_Name]", 0);
    setKey(cf, "[Depart_Loc].[Campus_Service_Name]", 0);
    setKey(cf, "[Depart_Loc].[Address]", 0);
    setKey(cf, "[Depart_Loc].[address]", 0);
  }
  
  // mask [Place_Name] if there is [Campus_Name] in *ef
  //
  if ( (val = getVal(ef, "[Depart_Loc].[Campus_Service_Name]")) ) {
    
    // mask [Place_Type] and [Address]
    //
    setKey(ef, "[Depart_Loc].[Place_Type]", 0);

    setKey(cf, "[Depart_Loc].[Place_Type]", 0);
    setKey(cf, "[Depart_Loc].[Place_Spec]", 0);
    setKey(cf, "[Depart_Loc].[Place_Name]", 0);
    setKey(cf, "[Depart_Loc].[Campus_Name]", 0);
    setKey(cf, "[Depart_Loc].[Building_Name]", 0);
    setKey(cf, "[Depart_Loc].[Address]", 0);
    setKey(cf, "[Depart_Loc].[address]", 0);
    campus_depart = 1;
  }
  
  // mask [Place_Spec] and [Place_Name] if new [Place_Type] comes
  //
  if ( (val = getVal(ef, "[Arrive_Loc].[Place_Type]")) ) {
    
    setKey(cf, "[Arrive_Loc].[Place_Name]", 0);   
    setKey(cf, "[Arrive_Loc].[Place_Spec]", 0);   
  }
  
  // mask [Place_Spec].good
  //
  if ( (val = getVal(ef, "[Arrive_Loc].[Place_Spec]")) ) {
    
    // we don't have resource to deal with "good"
    //
    if ( !scmp(val, "good") ) {
      setKey(ef, "[Arrive_Loc].[Place_Spec]", 0);   
    }
  }
  
  // print extracted frames
  printf("print after mask slot@@@@@@@@@@@@@@@@@@@@ef\n");
  print_frame(ef);
  printf("print after mask slot@@@@@@@@@@@@@@@@@@@@cf\n");
  print_frame(cf);
  
  return;
}

#if 0
/*
//char *check_query_address( aFrame **rframe) {
char	*prmpt;
aFrame	*frame;
int		xx;

*rframe= (aFrame *)0;

// if no query frames
if(!(frame= getFrame(context, "Query_Address", "first", &xx)) ) 
return( (char *)0 );

//mwe
//I left this comment in here but it no longer relates to our code at all
// set to first frame for optimize_price return
// 1. optimize_distance
//   2. optimize_price
//
//if( !scmp("optimize_distance", airmode) ) *rframe= frame;

// if declined by user
if(  !cmpVal(frame, "[Active]", "no") ) {
return( (char *)0 );
}

// check if all air frames complete
for(frame= getFrame(context, "Query_Address", "first", &xx); frame;
frame= getFrame(context, "Query_Address", "next", &xx)){

// if already accepted
if( !cmpVal(frame,"[accept]","yes")) {
// if nine_best accepted, nothing to check
if( !scmp("optimize_distance", airmode) ) {
*rframe= (aFrame *)0;
return( (char *)0 );
}
else  continue;
}

// if frame not complete, prompt for missing info
if( (prmpt= frame_complete(frame)) ) {
focus= frame;
return(prmpt);
}

// ************** specially handle [user_query] 

// if complete but not confirmed, then confirm 

// if not nine_best, return to generate dbq
if( scmp("optimize_distance", airmode) ) {
*rframe= frame;
return( (char *)0 );
}

}

return( (char *)0);
}
*/

/*
//char *check_query_list( aFrame **rframe) {

// question: airmode

char	*prmpt;
aFrame	*frame;
int		xx;


*rframe= (aFrame *)0;

// if no air frames 
if(!(frame= getFrame(context, "Query_List", "first", &xx)) )
return( (char *)0 );

// set to first frame for optimize_price return 
// 1. optimize_distance
2. optimize_price

//if( !scmp("optimize_distance", airmode) ) *rframe= frame;
*rframe= frame;

// if declined by user 
if(  !cmpVal(frame, "[Active]", "no") ) {
return( (char *)0 );
}

// check if all air frames complete 
for(frame= getFrame(context, "Query_List", "first", &xx); frame;
frame= getFrame(context, "Query_List", "next", &xx)){

// if already accepted 
if( !cmpVal(frame,"[accept]","yes")) {
// if nine_best accepted, nothing to check 
//if( !scmp("optimize_distance", airmode) ) {
*rframe= (aFrame *)0;
return( (char *)0 );
//}
//else  continue;
}

// if frame not complete, prompt for missing info 
if( (prmpt= frame_complete(frame)) ) {
focus= frame;
return(prmpt);
}

// ************** specially handle [user_query] 

// if complete but not confirmed, then confirm 

// if not nine_best, return to generate dbq 
//if( scmp("optimize_distance", airmode) ) {
*rframe= frame;
return( (char *)0 );
//}

}

return( (char *)0);
}

//char *check_query_direction( aFrame **rframe) {

printf("entering query_direction\n");

// question: airmode, 

char	*prmpt;
aFrame	*frame;
int		xx;


*rframe= (aFrame *)0;

// if no air frames 
if(!(frame= getFrame(context, "Query_Direction", "first", &xx)) )
return( (char *)0 );

// set to first frame for optimize_price return 
// 1. optimize_distance
2. optimize_price

//if( !scmp("optimize_distance", airmode) ) *rframe= frame;
*rframe= frame;

// if declined by user 
if(  !cmpVal(frame, "[Active]", "no") ) {
return( (char *)0 );
}

// check if all air frames complete 
for(frame= getFrame(context, "Query_Direction", "first", &xx); frame;
frame= getFrame(context, "Query_Direction", "next", &xx)){

// if already accepted 
if( !cmpVal(frame,"[accept]","yes")) {
// if nine_best accepted, nothing to check 
//if( !scmp("optimize_distance", airmode) ) {
*rframe= (aFrame *)0;
return( (char *)0 );
//}
//else  continue;
}

// if frame not complete, prompt for missing info 
if( (prmpt= frame_complete(frame)) ) {
focus= frame;
return(prmpt);
}

// ************** specially handle [user_query] 

// if complete but not confirmed, then confirm 

// if not nine_best, return to generate dbq 
//    if( scmp("optimize_distance", airmode) ) {
*rframe= frame;
return( (char *)0 );
//}

}

return( (char *)0);
}



//char *check_query_distance( aFrame **rframe) {

// question: airmode, 

char	*prmpt;
aFrame	*frame;
int		xx;


*rframe= (aFrame *)0;

// if no air frames 
if(!(frame= getFrame(context, "Query_Distance", "first", &xx)) )
return( (char *)0 );

// set to first frame for optimize_price return 
// 1. optimize_distance
2. optimize_price

//if( !scmp("optimize_distance", airmode) ) *rframe= frame;
*rframe= frame;

// if declined by user 
if(  !cmpVal(frame, "[Active]", "no") ) {
return( (char *)0 );
}

// check if all air frames complete 
for(frame= getFrame(context, "Query_Distance", "first", &xx); frame;
frame= getFrame(context, "Query_Distance", "next", &xx)){

// if already accepted 
if( !cmpVal(frame,"[accept]","yes")) {
// if nine_best accepted, nothing to check 
//if( !scmp("optimize_distance", airmode) ) {
*rframe= (aFrame *)0;
return( (char *)/0 );
//}
//else  continue;
}

// if frame not complete, prompt for missing info 
if( (prmpt= frame_complete(frame)) ) {
focus= frame;
return(prmpt);
}

// ************** specially handle [user_query] 

// if complete but not confirmed, then confirm 

// if not nine_best, return to generate dbq 
//if( scmp("optimize_distance", airmode) ) {
*rframe= frame;
return( (char *)0 );
//}

}

return( (char *)0);
}

char *check_query_building( aFrame **rframe) {

// question: airmode, 

char	*prmpt;
aFrame	*frame;
int		xx;


*rframe= (aFrame *)0;

// if no air frames 
if(!(frame= getFrame(context, "Query_Building", "first", &xx)))
return( (char *)0 );

// set to first frame for optimize_price return 
// 1. optimize_distance
2. optimize_price

//if( !scmp("optimize_distance", airmode) ) *rframe= frame;
*rframe= frame;

// if declined by user 
if(  !cmpVal(frame, "[Active]", "no") ) {
return( (char *)0 );
}

// check if all air frames complete 
for(frame= getFrame(context, "Query_Building", "first", &xx); frame;
frame= getFrame(context, "Query_Building", "next", &xx)){

// if already accepted 
if( !cmpVal(frame,"[accept]","yes")) {
// if nine_best accepted, nothing to check 
//if( !scmp("optimize_distance", airmode) ) {
*rframe= (aFrame *)0;
return( (char *)0 );
//}
//else  continue;
}

// if frame not complete, prompt for missing info 
if( (prmpt= frame_complete(frame)) ) {
focus= frame;
return(prmpt);
}

// ************** specially handle [user_query] 

// if complete but not confirmed, then confirm 

// if not nine_best, return to generate dbq 
//if( scmp("optimize_distance", airmode) ) {
*rframe= frame;
return( (char *)0 );
//}

}

return( (char *)0);
}
*/
#endif
