#include <stddef.h>
#include <assert.h>
#include <ctype.h>

#include "FTreg.h"
#include "string.h"
#include "memory.h"
#include "useful.h"

static char *parser(str)
const char *str;
{
  char *temp_buffer;
  int str_len;

  assert(str != (const char *)NULL);
  str_len = strlen(str);

  temp_buffer = (char *)Memory_allocate(str_len+1);
  strcpy(temp_buffer, str);
  return temp_buffer;
}

static const char *un_parser(s)
const char *s;
{
  return s;
}

/* ### ### replace with DFA or Boyer-Moore code for efficency ### ### */
/*--------------------------------------------------*/
static int comma_one_contains(text,pattern)
const char *pattern, *text;
{
  int i, last_index, length_of_pattern;

  assert(pattern != (const char *)NULL && text != (const char *)NULL);

  length_of_pattern = strlen(pattern);
  last_index = strlen(text) - length_of_pattern + 1;

  if (last_index > 0) {
    for (i=0; i < last_index; i++) {
      if (strncmp(pattern, &(text[i]), length_of_pattern) == 0) {
	return 1;
      }
    }
  }

  /* pattern too long or pattern not found */
  return 0;
}

/*--------------------------------------------------*/
static int comma_contains(text,pattern)
const char *pattern, *text;
{
  Darray patternD=Darray_create();
  int i,l;
  RapList_parse_list_into_darray(patternD,pattern);
  l=Darray_len(patternD);
  for (i=0;i<l;i++) 
    if (comma_one_contains(text,Darray_get(patternD,i))) {
      RapList_destroy_darray_contents(patternD);
      Darray_destroy(patternD);
      return(1);
    }
  RapList_destroy_darray_contents(patternD);
  Darray_destroy(patternD);
  return(0);
}


/*--------------------------------------------------*/
static int comma_one_contains_word(text,pattern)
const char *pattern, *text;
{
  int i, last_index, length_of_pattern;

  assert(pattern != (const char *)NULL && text != (const char *)NULL);

  length_of_pattern = strlen(pattern);
  last_index = strlen(text) - length_of_pattern + 1;

  if (last_index > 0) {
    for (i=0; i < last_index; i++) {
      if (((i==0) || !isalpha(text[i-1])) &&
	  ((i == last_index) || !isalpha(text[i+length_of_pattern])) &&
	  (strncmp(pattern, &(text[i]), length_of_pattern) == 0)) {
	return 1;
      }
    }
  }

  /* pattern too long or pattern not found */
  return 0;
}

/*--------------------------------------------------*/
static int comma_contains_word(text,pattern)
const char *pattern, *text;
{
  Darray patternD=Darray_create();
  int i,l;
  RapList_parse_list_into_darray(patternD,pattern);
  l=Darray_len(patternD);
  for (i=0;i<l;i++) 
    if (comma_one_contains_word(text,Darray_get(patternD,i))) {
      RapList_destroy_darray_contents(patternD);
      Darray_destroy(patternD);
      return(1);
    }
  RapList_destroy_darray_contents(patternD);
  Darray_destroy(patternD);
  return(0);
}


static int comma_one_equal(value, pattern)
const char *value, *pattern;
{
  return (strcmp(pattern, value) == 0);
}


/*--------------------------------------------------*/
static int comma_equal(text,pattern)
const char *pattern, *text;
{
  Darray patternD=Darray_create();
  int i,l;
  RapList_parse_list_into_darray(patternD,pattern);
  l=Darray_len(patternD);
  for (i=0;i<l;i++) 
    if (comma_one_equal(text,Darray_get(patternD,i))) {
      RapList_destroy_darray_contents(patternD);
      Darray_destroy(patternD);
      return(1);
    }
  RapList_destroy_darray_contents(patternD);
  Darray_destroy(patternD);
  return(0);
}


static int comma_one_less(value, pattern)
const char *value, *pattern;
{
  return (strcmp(pattern, value) < 0);
}

/*--------------------------------------------------*/
static int comma_less(text,pattern)
const char *pattern, *text;
{
  Darray patternD=Darray_create();
  int i,l;
  RapList_parse_list_into_darray(patternD,pattern);
  l=Darray_len(patternD);
  for (i=0;i<l;i++) 
    if (comma_one_less(text,Darray_get(patternD,i))) {
      RapList_destroy_darray_contents(patternD);
      Darray_destroy(patternD);
      return(1);
    }
  RapList_destroy_darray_contents(patternD);
  Darray_destroy(patternD);
  return(0);
}


static int comma_one_greater(value, pattern)
const char *value, *pattern;
{
  return (strcmp(pattern, value) > 0);
}

/*--------------------------------------------------*/
static int comma_greater(text,pattern)
const char *pattern, *text;
{
  Darray patternD=Darray_create();
  int i,l;
  RapList_parse_list_into_darray(patternD,pattern);
  l=Darray_len(patternD);
  for (i=0;i<l;i++) 
    if (comma_one_greater(text,Darray_get(patternD,i))) {
      RapList_destroy_darray_contents(patternD);
      Darray_destroy(patternD);
      return(1);
    }
  RapList_destroy_darray_contents(patternD);
  Darray_destroy(patternD);
  return(0);
}


static NORET comma_free(data)
char *data;
{
  Memory_free((VOIDP)data);
}

static FieldOpArg fieldOpList[]={
  { "%contains", comma_contains },
  { "%contains_word", comma_contains_word },
  { "%is_equal_to",comma_equal },
  { "%equals",comma_equal },
  { "=",comma_equal },
  { "%is_less_than", comma_less },
  { "%less",comma_less },
  { "<",comma_less },
  { "%is_greater_than", comma_greater },
  { "%greater_than", comma_greater },
  { "%greater", comma_greater },
  { ">",comma_greater },
  { (char *)NULL, (FieldOperatorProc *)NULL }
};

static struct AlFieldTypeRegistry_str  comma_FTrec={
  "Same-Case-Text-with-commas-as-ORs",
  parser,
  un_parser,
  fieldOpList,
  NULL,
  NULL,
  comma_free,
};

struct AlFieldTypeRegistry_str  *comma_FTrecptr = &comma_FTrec;
