#include <stddef.h>
#include <stdio.h>
#include <string.h>

#include "memory.h"
#include "end.h"
#include "FieldCoreP.h"
#include "FieldType.h"
#include "FieldTypeP.h"
#include "al.h"

  /* please don't be alarmed by this line--it doesn't concern you */
#include "FTreg.h"

#ifndef PRINT_TO
#define PRINT_TO stderr
#endif PRINT_TO

/*---------------------------*/
void AlFieldCore_print(fc)
AlFieldCore fc;
{
 fprintf(PRINT_TO,"AlFieldCore::key='%s'\n",fc->key);
}
/*---------------------------*/
AlFieldCore AlFieldCore_create(fieldTypeName)
const char *fieldTypeName;
{
  AlFieldCore fc;

  fc=(AlFieldCore)Memory_allocate(sizeof(struct AlFieldCore_str));
  fc->key=NULL;
  if (strcmp(fieldTypeName,"test")!=0) {
    fc->AlFieldType=AlFieldType_get_field_type(fieldTypeName);
    if (fc->AlFieldType==NULL)  
      Al_fatal_error1("Field Type \"%s\" does not exist\n",fieldTypeName);
  }
  else 
    fc->AlFieldType=NULL;
  fc->fieldTypeName=(char *)Memory_allocate(strlen(fieldTypeName)+1);
  strcpy(fc->fieldTypeName,fieldTypeName);
  fc->print_self=AlFieldCore_print;
  fc->parsedData=NULL;
  return(fc);
}

/*---------------------------*/
AlFieldCore AlFieldCore_create_with_obj(obj)
AlFieldType obj;
{
  const char *ftn;
  AlFieldCore fc;
  if (AlFTreg_exists_obj(obj)==Bool_FALSE)
    FEnd("AlFieldCore_create_with_obj: invalid object passed in");
  fc=(AlFieldCore)Memory_allocate(sizeof(struct AlFieldCore_str));
  fc->key=NULL;
  fc->AlFieldType=obj;
  ftn=AlFTreg_obj_to_string(obj);
  fc->fieldTypeName=(char *)Memory_allocate(strlen(ftn)+1);
  strcpy(fc->fieldTypeName,ftn);
  fc->print_self=AlFieldCore_print;
  fc->parsedData=NULL;
  return(fc);
}
/*------------------------*/
Bool AlFieldCore_compare_with_field_op(fc1,fc2,Operation)
AlFieldCore fc1,fc2;
FieldOperatorProc *Operation;
{
  int Result;
  
  if (AlFieldType_equal(fc1->AlFieldType,fc2->AlFieldType)==Bool_FALSE) {
   printf("ERROR: Field Core: Comapring two fields of different types ^^^2\n");
    return(Bool_FALSE);
  }
  if ((strcmp(fc1->key,fc2->key))!=0) {
    printf("WARNING: Field Core-compare with field op: keys don't match\n");
    printf("         '%s'  is not equal to  '%s' ^^^1\n", fc1->key, fc2->key);
  }
  if (fc1->parsedData==NULL ) {
    printf("ERROR: Field Core: comparing two fields when one is not parsed\n");
    printf("       Field Core key =%s ^^^3\n",fc1->key);
    return(Bool_FALSE);
  }
  if (fc2->parsedData==NULL ) {
    printf("ERROR: Field Core: comparing two fields when one is not parsed\n");
    printf("       Field Core key =%s ^^^4\n",fc2->key);
    return(Bool_FALSE);
  }
  if (Operation==NULL)  {
    printf("Comparing Field Cores: operator not valid\n");
    return(Bool_FALSE);
  }
  Result=(*Operation)(fc1->parsedData,fc2->parsedData);
  if (Result==1)
    return(Bool_TRUE);
  else
    return(Bool_FALSE);
}

/*--------------------------*/
void AlFieldCore_delete(fc)
AlFieldCore fc;
{
  if (fc==NULL)  {
    printf("FieldCore_delete: ERROR, passed in NULL FieldCore object\n");
    return;
  }
  if (fc->parsedData!=NULL)
    (fc->AlFieldType->free_parsed_data)(fc->parsedData);
  if (fc->key!=NULL)
    Memory_free(fc->key);
  if (fc->fieldTypeName!=NULL)
    Memory_free(fc->fieldTypeName);
  else  {
    printf("AlFieldCore_delete: invalid FieldCore object,no FieldType name\n");
    printf("                    deleting rest anyway.\n");
  }
  Memory_free(fc);
}
/*--------------------------*/
void AlFieldCore_destroy(fc)
AlFieldCore fc;
{
  AlFieldCore_delete(fc);
}

/*-----------------------*/
AlFieldCore AlFieldCore_duplicate(fc)
AlFieldCore fc;
{
  AlFieldCore d;
  d=AlFieldCore_create(fc->fieldTypeName);
  d->key=(char *)Memory_allocate(strlen(fc->key)+2);
  strcpy(d->key,fc->key);
  d->fieldTypeName=(char *)Memory_allocate(strlen(fc->fieldTypeName)+2);
  strcpy(d->fieldTypeName,fc->fieldTypeName);
  d->AlFieldType=fc->AlFieldType;
  d->print_self=fc->print_self;
  return(d);
}
/*---------------------------*/
void AlFieldCore_set_key(fc,key)
AlFieldCore  fc;
const char *     key;
{
  fc->key=(char *)Memory_allocate(strlen(key)+2);
  strcpy(fc->key,key);
}
/*---------------------------*/
const char *AlFieldCore_get_key(fc)
AlFieldCore fc;
{
  return(fc->key);
}
/*------------------------*/
Bool AlFieldCore_parse(fc,value)
AlFieldCore fc;
const char *value;
{
  if (fc->parsedData!=NULL)
    (fc->AlFieldType->free_parsed_data)(fc->parsedData);
  fc->parsedData=(fc->AlFieldType->parser)(value);
  if (fc->parsedData==NULL)  return(Bool_FALSE);
  else return(Bool_TRUE);
}
/*-----------------------*/
const char *AlFieldCore_un_parse(fc)
AlFieldCore fc;
{
  return ((fc->AlFieldType->un_parser)(fc->parsedData));
}
/*---------------------*/
Bool AlFieldCore_equal(fc1,fc2)
AlFieldCore fc1, fc2;
{
  if (strcmp(fc1->key,fc2->key)==0 && strcmp(fc1->fieldTypeName,
					     fc2->fieldTypeName)==0)
    return(Bool_TRUE);
  else
    return(Bool_FALSE);
}

/*-------------------------*/
const char *    AlFieldCore_get_field_type_name(fc)
AlFieldCore fc;
{
  return(fc->fieldTypeName);
}
/*-------------------------*/
AlFieldType   AlFieldCore_get_field_type(fc)
AlFieldCore fc;
{
  return(fc->AlFieldType);
}

/*-----------------------*/
void AlFieldCore_set_field_type(fc,ft)
AlFieldCore fc;
AlFieldType ft;
{
  const char *ftn;
  fc->AlFieldType=ft;
  if (fc->fieldTypeName!=NULL)
    Memory_free(fc->fieldTypeName);
  ftn=AlFTreg_obj_to_string(ft);
  fc->fieldTypeName=(char *)Memory_allocate(strlen(ftn)+1);
  strcpy(fc->fieldTypeName,ftn);
}
