#include "assert.h"   /* must be first for use eith hc2 */
#include "ArgPack.h"
#include "Mintrins.h"
#include "alfonts.h"
#include "alpop.h"
#include "alxms.h"
#include "d2field.h"
#include "d2fieldargs.h"
#include "d2args.h"
#include "darray.h"
#include "debug.h"
#include "menupack.h"
#include "rem.h"
#include "widgets.h"
#include "xstuff.h"
#include <Xm/BulletinB.h>
#include <Xm/PanedW.h>
#include <Xm/Separator.h>

  extern NORET d2_KeyModify_CB  PROTOTYPE((Widget,reid,caddr_t));

MenuPack d2_Field_make_key_menu PROTOTYPE((REField));

/*--------------------------------------------------*/
Widget d2_Field_create(field,parentW,previousW)
     REField field;
     Widget parentW,previousW;
{
  reid rei=field->rei;
  ArgPack AP;
  AP=ArgPack_duplicate_args(d2_field_form);
  if (previousW==NULL)
    ArgPack_add_arg(AP, XmNtopAttachment, (XtArgVal) XmATTACH_FORM );
  else {
    ArgPack_add_arg(AP, XmNtopAttachment, (XtArgVal) XmATTACH_WIDGET );
    ArgPack_add_arg(AP, XmNtopWidget, (XtArgVal) previousW );
  }
  ArgPack_add_arg(AP, XmNheight, (XtArgVal) rei->if_field_height );
  ArgPack_add_arg(AP, XmNtopOffset, (XtArgVal) rei->if_field_spacing ); 
  field->ContainerW=XmCreateForm(parentW,
				 "field-container",
				 ArgPack_the_args(AP),
				 ArgPack_num_args(AP));
  ArgPack_delete(AP);

  if (rei->Mode==RE_MODE_SIMPLE)
    d2_Field_create_simple(field);
  else 
    d2_Field_create_complex(field);
  
  return(field->ContainerW);
}

/*--------------------------------------------------*/
NORET d2_Field_create_simple(field)
     REField field;
{
  Widget  AltsMenuW, FTMenuW, SW, IFCW, button;
  ArgPack AP;
  REField REPreviousField, Field;
  REMember remt;
  char *FieldClassName, *trans;
  int ValueX, AltsMenuX, KeyX, vbl;
  reid rei=field->rei;
  extern NORET Alxt_center_text_in_text_widget();

  if (field->IsState==Bool_FALSE)  {
    AP=ArgPack_duplicate_args(d2_field_edit);
    ArgPack_add_arg(AP, XmNleftAttachment, (XtArgVal) XmATTACH_FORM );
    ArgPack_add_arg(AP, XmNrightAttachment, (XtArgVal)  XmATTACH_NONE/*7*/ );
    ArgPack_add_arg(AP, XmNmaxLength, (XtArgVal) field->MaxKeyLength );
    ArgPack_add_arg(AP, XmNcursorPosition,(XtArgVal)  strlen(field->Key));
    ArgPack_add_arg(AP, XmNvalue, (XtArgVal) field->Key);
    ArgPack_add_arg(AP, XmNresizeWidth, (XtArgVal) FALSE  );
    ArgPack_add_arg(AP, XmNheight, (XtArgVal) rei->if_field_height );
    ArgPack_add_arg(AP, XmNcursorPosition,(XtArgVal) 
		    strlen(field->ValueBuffer));
    field->KeyW=XtCreateManagedWidget("field-key",
				      xmTextWidgetClass,
				      field->ContainerW,
				      ArgPack_the_args(AP),
				      ArgPack_num_args(AP));
    ArgPack_delete(AP);
    
    XtAddCallback(field->KeyW,XmNvalueChangedCallback,
		  d2_KeyModify_CB,
		  field->rei);
    XtAddCallback(field->KeyW,XmNfocusCallback,
		  ed_Select_field_CB,
		  field);
  }
  else {
    field->KeyMenu=d2_Field_make_key_menu(field);
    AP=ArgPack_duplicate_args(d2_field_edit_menu);
    ArgPack_add_arg(AP, XmNtopAttachment, (XtArgVal) XmATTACH_FORM );
    ArgPack_add_arg(AP, XmNheight, (XtArgVal) rei->if_field_height );
    MenuPack_option_set_args(field->KeyMenu,AP);
    MenuPack_attach_to_widget(field->KeyMenu,field->ContainerW);
    MenuPack_make_menu(field->KeyMenu);
    ArgPack_delete(AP);
  }
  
  if (field->ShowOp==Bool_TRUE) {
    AP=ArgPack_duplicate_args(d2_field_option_menu);
    ArgPack_add_arg(AP, XmNheight, (XtArgVal) rei->if_field_height );
    ArgPack_add_arg(AP, XmNleftAttachment, (XtArgVal) XmATTACH_WIDGET );
    ArgPack_add_arg(AP, XmNrightAttachment, (XtArgVal) XmATTACH_NONE );
    ArgPack_add_arg(AP, XmNleftWidget, (XtArgVal) field->KeyW );
    MenuPack_option_set_args(field->OpMenu,AP);
    MenuPack_attach_to_widget(field->OpMenu,field->ContainerW);
    MenuPack_make_menu(field->OpMenu);
    ArgPack_delete(AP);
    field->OpW=MenuPack_get_top_level_manager(field->OpMenu);
    
    Alxt_SetArg(field->OpW,XmNheight, (XtArgVal) rei->if_field_height ); 
    Alxt_SetArg(field->OpW,XmNmarginWidth, (XtArgVal) 0 );

    button=MenuPack_option_get_button(field->OpMenu);
    Alxt_SetArg(button,XmNheight, (XtArgVal) rei->if_field_height );
    Alxt_SetArg(button,XmNtraversalOn, (XtArgVal) TRUE );
    /* Alxt_SetArg(button,XmNshadowThickness, (XtArgVal) 50); */
    
    /* XtDestroyWidget(MenuPack_option_get_label(field->OpMenu)); */

  }

  /*
   * ADD THE VALUE WIDGET FIRST
   */
  AP=ArgPack_duplicate_args(d2_field_edit);
  ArgPack_add_arg(AP, XmNmaxLength, (XtArgVal) field->MaxValueBufferLength );
  ArgPack_add_arg(AP, XmNrightAttachment, (XtArgVal)  XmATTACH_FORM/*7*/ );
  ArgPack_add_arg(AP, XmNleftAttachment, (XtArgVal)  XmATTACH_WIDGET );
  if (field->ShowOp==Bool_TRUE)
    ArgPack_add_arg(AP, XmNleftWidget, (XtArgVal)  field->OpW  );
  else {
    ArgPack_add_arg(AP, XmNleftWidget, (XtArgVal)  field->KeyW  );
  }
  ArgPack_add_arg(AP, XmNvalue, (XtArgVal)  field->ValueBuffer);
  ArgPack_add_arg(AP, XmNresizeWidth, (XtArgVal) TRUE  );
  ArgPack_add_arg(AP, XmNheight, (XtArgVal) rei->if_field_height );
  field->ValueW=XtCreateManagedWidget("field-value",
				      xmTextWidgetClass,
				      field->ContainerW,
				      ArgPack_the_args(AP),
				      ArgPack_num_args(AP));
  XtAddCallback(field->ValueW,XmNfocusCallback,
		ed_Select_field_CB,
		field);
  ArgPack_delete(AP);


  /* attempt to vertically center text in text widgets 
  Alxt_center_text_in_text_widget(field->ValueW);
  Alxt_center_text_in_text_widget(field[11~->KeyW); */

  RE_debug("added simple valuueW.\n");

}

/*--------------------------------------------------*/
NORET d2_Field_create_complex(field)
     REField field;
{
  Widget  AltsMenuW, FTMenuW, SW, IFCW, button;
  ArgPack AP;
  REField REPreviousField, Field;
  REMember remt;
  char *FieldClassName, *trans;
  int ValueX, AltsMenuX, KeyX, vbl;
  reid rei=field->rei;
  extern NORET Alxt_center_text_in_text_widget();

  d2_Field_create_simple(field);

  /*
  field->ClassMenu=d2_Field_create_class_menu(field);
  AP=ArgPack_duplicate_args(d2_field_menu);
  ArgPack_add_arg(AP, XmNtopAttachment, (XtArgVal)    XmATTACH_FORM );
  ArgPack_add_arg(AP, XmNleftAttachment, (XtArgVal)   XmATTACH_FORM );
  ArgPack_add_arg(AP, XmNrightAttachment, (XtArgVal)  XmATTACH_NONE );
  ArgPack_add_arg(AP, XmNbottomAttachment, (XtArgVal) XmATTACH_NONE );
  ArgPack_add_arg(AP, XmNheight, (XtArgVal) rei->if_field_height );
  MenuPack_option_set_args(field->ClassMenu,AP);
  MenuPack_attach_to_widget(field->ClassMenu,field->ClassFrameW); 
  MenuPack_make_menu(fe->ClassMenu);
  ArgPack_delete(AP);
  
  Alxt_set_widget_feature(field->KeyW,XmNtopAttachment,XmATTACH_WIDGET);
  */
}


/*--------------------------------------------------*/
NORET d2_Field_select_FT_CB(w,rap,data)
Widget w;
RapPack rap;
caddr_t data;
{
  Widget ShellW;
  char  *string;
  AlFieldType FT;
  Darray Ops=Darray_create();
  REField field=(REField)  RapPack_get(rap,0);
  char* newFieldType=(char*)RapPack_get(rap,1);
  reid rei=field->rei;
  ArgPack AP;

  /* free up the old string and replace with the new one */
  Memory_free(field->FieldType);
  field->FieldType=RapStr_duplicate(newFieldType);
  FT=AlFTreg_string_to_obj(field->FieldType);
  field->FieldTypeObject=FT;

  /* get the default field operator which is the first one in the list of */
  if ((AlFieldType_get_field_op_list(FT,Ops))==Bool_FALSE)
    Al_fatal_error("couldn;t get default field operator\n");
  string=(char *)Darray_get(Ops,(unsigned)0);
  assert(field->FieldOp);
  if (strcmp(field->FieldOp,string)!=0) {
    /* REMAKE THE FIELD OPERATORS MENU*/
    field->FieldOp=RapStr_duplicate(string);
    if (field->OpW!=NULL) {
      XtDestroyWidget(field->OpW);
    }
    if (field->OpMenu!=NULL)
      MenuPack_destroy(field->OpMenu);
    /* field->OpMenu=d2_MakeOpMenu(field,FT); */
  }
}


/*--------------------------------------------------
MenuPack d2_Field_make_type_menu(field)
     REField field;
{
  MenuPack mp;
  RapPack rap;
  int i, l;
  char *name;

  mp=MenuPack_create_option(NULL,"field-dialog-type-menu","The value in this field is of type ");
  l=Darray_len(FieldTypePresOrder_GR);
  for (i=0;i<l;i++) {
    name=(char*)Darray_get(FieldTypePresOrder_GR,i);
    rap=RapPack_create2(fe,name);
    MenuPack_add_option(name,mp,
			(XtCallbackProc)d2_Select_FT_CB,
			(caddr_t)rap, NULL);
  }
  return(mp);
}
*/

/*--------------------------------------------------*/
void d2_Field_select_FC_CB(w,rap,cadda)
     Widget w;
     RapPack rap;
     caddr_t cadda;
{
  ArgPack AP;
  Widget SW;
  RapPack rap2;
  REField field=(REField)RapPack_get(rap,0);
  char *ft;
  char *    name=(char*)RapPack_get(rap,1);
  reid rei=field->rei;
  AlRFType Class=(AlRFType)AlRule_get_class_from_name(name);

    /* maybe this should reset defaults instead of just returning */
  if (Class==field->Type) return;
  if (field->FieldClass!=NULL)
    Memory_free(field->FieldClass);
  field->FieldClass=RapStr_duplicate(name);
  field->Type=Class;
  
  /*
   * if we have changed to a state then we must alter the field type
   * appropriately 
   */
  /*ft=Registry_get(StateFCnames_to_FTnames_GR,
		  field->FieldClass); */
  rap2=RapPack_create2(field,ft);
    
  /* god what a sneaky trick */
  d2_Field_select_FT_CB(w,rap2,NULL);
  
  /* previous call doesn't do this visuallyt */
  MenuPack_set_as_default(field->TypeMenu,field->FieldType);
}



/*--------------------------------------------------*/
MenuPack d2_Field_make_class_menu(field)
     REField field;
{
  AlRFType Class;
  MenuPack mmp;
  RapPack rap;
  unsigned i,l;
  char *name;
  Darray FCs=Darray_create();
  Darray PSs=Darray_create();
  Darray MPs=Darray_create();
  
  AlRule_get_field_class_names(FCs);
  AlRule_get_processing_state_names(PSs);
  AlRule_get_message_property_names(MPs);

  mmp=MenuPack_create_option(NULL,"field-dialog-class-menu",NULL);
  l=Darray_len(FCs);
  for (i=0;i<l;i++) {
    name=Darray_get(FCs,i);
    rap=RapPack_create2(field,name);
    MenuPack_add_option(name,mmp,
			(XtCallbackProc)d2_Field_select_FC_CB,
			(caddr_t)rap,NULL);
  }
  Darray_destroy(FCs);
  Darray_destroy(PSs);
  Darray_destroy(MPs);

  return(mmp);
}

/*--------------------------------------------------*/
NORET d2_Field_key_menu_CB(w,rap,cadda)
     Widget w;
     RapPack rap;
     caddr_t cadda;
{
  REField  field=(REField)RapPack_get(rap,0);
  char* state=(char*)RapPack_get(rap,1);
  
  field->Type=AlRule_get_class_from_name(state);
  RE_debug1("key menu state=%s\n",state);
}


/*--------------------------------------------------*/
MenuPack d2_Field_make_key_menu(field)
     REField field;
{
  AlRFType class=field->Type;
  MenuPack mp;
  int i, l;
  Darray names=Darray_create();
  RapPack rap;
  char *name;

  mp=MenuPack_create_option(NULL,"field-key-menu","");
  if (AlRule_is_processing_state(class)) 
    AlRule_get_processing_state_names(names);
  else if (AlRule_is_message_property(class))
    AlRule_get_message_property_names(names);
  l=Darray_len(names);
  for (i=0;i<l;i++) {
    name=(char*)Darray_get(names,i);
    rap=RapPack_create2(field,name);
    MenuPack_add_option(name,mp,
			(XtCallbackProc)d2_Field_key_menu_CB,
			(caddr_t)rap, NULL);
  }
  return(mp);
}

