#ifndef _RULE_H_
#define _RULE_H_

#include <bool.h>
#include <flags.h>
#include <sys/types.h>

#include "darray.h"
#include "FieldCore.h"
#include "FieldType.h"

#define RST_DEL BIT(0)
#define RST_NEW BIT(1)
#define RST_CHG BIT(2)

typedef int	r_state;

typedef struct st_AlRuleAssoc	*AlRuleAssoc;
typedef struct st_AlRuleField	*AlRuleField;
typedef struct st_AlRuleMember	*AlRuleMember;
typedef struct st_AlRule	*AlRule;

/* ALRFT_MSG -- Field Type Message */
/* ALRFT_UP -- Field Type User Property */
/* ALRFT_FI -- Field Type Folder-specific info */
/* ALRFT_SMF -- Field Type State, Moved From */
/* ALRFT_SNTM -- State, Number of Times Moved */
/* ALRFT_SNRF -- State, Number of Rules Fired */
/* ALRFT_SNOF -- State, Number Of Fields */
/* ALRFT_SMLL -- State, Message Line Length */
/* ALRFT_SMCL -- State, Message Character Length */
/* ALRFT_SBLL -- State, Body Line Length */
/* ALRFT_SBCL -- State, Body Character Length */
/* ALRFT_SNUB -- State, Number of Unprintables in Body */
/* ALRFT_SFC -- State, Field Count */

#ifdef __STDC__
typedef enum ALRMType_en {ALRMT_ASSOC, ALRMT_FIELD} AlRMType;
typedef enum ALRAType_en {ALRAT_AND, ALRAT_OR, ALRAT_NOT} AlRAType;
typedef enum AlRFType_en {ALRFT_MSG, ALRFT_UP, ALRFT_FI, ALRFT_SMF, 
			  ALRFT_SNTM, ALRFT_SNRF, ALRFT_SNOF, ALRFT_SMLL, 
			  ALRFT_SMCL, ALRFT_SBLL, ALRFT_SBCL, ALRFT_SNUB, 
			  ALRFT_SFC} AlRFType;

extern AlRule		AlRule_create(AlRuleMember, Darray, time_t, time_t, char *);
extern AlRule		AlRule_copy(AlRule);
extern NORET		AlRule_destroy(AlRule);
extern AlRuleMember	AlRule_get_predicate(AlRule);
extern Darray		AlRule_get_actions(AlRule);
extern time_t		AlRule_get_creation(AlRule);
extern time_t		AlRule_get_update(AlRule);
extern char *		AlRule_get_name(AlRule);
extern char *		AlRule_set_name(AlRule, char *);
extern NORET		AlRule_mark_changed(AlRule);
extern NORET		AlRule_mark_unchanged(AlRule);
extern AlRuleMember	AlRuleMember_mcreate_assoc(AlRAType);
extern AlRuleMember	AlRuleMember_mcreate_field( 
						   AlRFType, char *, 
						   char *, char *, char *);
extern AlRuleMember	AlRuleMember_mcreate_field_no_parse( 
						   AlRFType, char *, 
						   char *, char *, char *);
extern AlRuleMember	AlRuleMember_copy(AlRuleMember);
extern NORET		AlRuleMember_destroy(AlRuleMember);
extern NORET		AlRuleMember_insert_after(AlRuleMember, AlRuleMember);
extern NORET		AlRuleAssoc_make_member_of(AlRuleAssoc, AlRuleMember);
extern AlRuleMember	AlRuleAssoc_as_member(AlRuleAssoc);
extern AlRuleAssoc	AlRuleMember_remove(AlRuleMember);
extern AlRMType		AlRuleMember_get_type(AlRuleMember);
extern AlRAType		AlRuleAssoc_get_type(AlRuleAssoc);
extern const char *	AlRuleAssoc_atype(AlRAType);
extern AlRFType		AlRuleField_get_type(AlRuleField);
extern NORET		AlRuleField_set_key(AlRuleField, char *);
extern Bool		AlRuleField_set_value(AlRuleField, char *);
extern Bool		AlRuleField_set_type(AlRuleField, char *);
extern Bool		AlRuleField_set_op(AlRuleField, char *);
extern AlRuleMember	AlRuleField_as_member(AlRuleField);
extern AlRuleAssoc	AlRuleMember_get_assoc(AlRuleMember);
extern AlRuleField	AlRuleMember_get_field(AlRuleMember);
extern AlRuleMember	AlRuleMember_get_sibling(AlRuleMember);
extern AlRuleMember	AlRuleMember_get_previous(AlRuleMember);
extern AlRuleMember	AlRuleAssoc_get_first_member(AlRuleAssoc);
extern Darray		AlRuleAssoc_get_contents(AlRuleAssoc, Darray);
extern AlFieldCore	AlRuleField_get_fc(AlRuleField);
extern char *		AlRuleField_get_strvalue(AlRuleField);
extern char *		AlRuleField_get_op_name(AlRuleField);
extern FieldOperatorProc *AlRuleField_get_op_func(AlRuleField);
extern AlRuleAssoc      AlRuleMember_get_container(AlRuleMember);
extern Bool             AlRuleField_test_contents(AlRuleField);
extern Bool             AlRule_is_state(AlRFType);
extern Bool             AlRule_is_processing_state(AlRFType);
extern Bool             AlRule_is_message_property(AlRFType);
extern NORET            AlRule_get_field_class_names(Darray);
extern NORET            AlRule_get_processing_state_names(Darray);
extern NORET            AlRule_get_message_property_names(Darray);
extern char*            AlRule_get_field_class_default_field_type(AlRFType);
extern AlRFType         AlRule_get_class_from_name(char*);
extern char*            AlRule_get_name_from_class(AlRFType);
extern AlRule           AlRule_create_default_rule();
#else
typedef int	AlRMType;
typedef int	AlRAType;
typedef int	AlRFType;
#define ALRMT_ASSOC	0
#define ALRMT_FIELD	1
#define ALRAT_AND	0
#define ALRAT_OR	1
#define ALRAT_NOT	2
#define ALRFT_MSG	0
#define ALRFT_UP	1
#define ALRFT_FI	2
#define ALRFT_SMF	3
#define ALRFT_SNTM	4
#define ALRFT_SNRF	5
#define ALRFT_SNOF	6
#define ALRFT_SMLL	7
#define ALRFT_SMCL	8
#define ALRFT_SBLL	9
#define ALRFT_SBCL	10
#define ALRFT_SNUB	11
#define ALRFT_SFC	12

extern AlRule		AlRule_create();
extern AlRule		AlRule_copy();
extern NORET		AlRule_destroy();
extern AlRuleMember	AlRule_get_predicate();
extern Darray		AlRule_get_actions();
extern time_t		AlRule_get_creation();
extern time_t		AlRule_get_update();
extern char *		AlRule_get_name();
extern char *		AlRule_set_name();
extern NORET		AlRule_mark_changed();
extern NORET		AlRule_mark_unchanged();
extern AlRuleMember	AlRuleMember_mcreate_assoc();
extern AlRuleMember	AlRuleMember_mcreate_field();
extern AlRuleMember	AlRuleMember_mcreate_field_no_parse();
extern AlRuleMember	AlRuleMember_copy();
extern NORET		AlRuleMember_destroy();
extern NORET		AlRuleMember_insert_after();
extern NORET		AlRuleAssoc_make_member_of();
extern AlRuleMember	AlRuleAssoc_as_member();
extern AlRuleAssoc	AlRuleMember_remove();
extern AlRAType		AlRuleAssoc_get_type();
extern char *	        AlRuleAssoc_atype();
extern AlRFType		AlRuleField_get_type();
extern NORET		AlRuleField_set_key();
extern Bool		AlRuleField_set_value();
extern Bool		AlRuleField_set_type();
extern Bool		AlRuleField_set_op();
extern AlRuleMember	AlRuleField_as_member();
extern AlRuleAssoc	AlRuleMember_get_assoc();
extern AlRuleField	AlRuleMember_get_field();
extern AlRuleMember	AlRuleMember_get_sibling();
extern AlRuleMember	AlRuleMember_get_previous();
extern AlRuleMember	AlRuleAssoc_get_first_member();
extern Darray		AlRuleAssoc_get_contents();
extern AlFieldCore	AlRuleField_get_fc();
extern char *		AlRuleField_get_strvalue();
extern char *		AlRuleField_get_op_name();
extern FieldOperatorProc *AlRuleField_get_op_func();
extern AlRuleAssoc      AlRuleMember_get_container();
extern Bool             AlRuleField_test_contents();
extern Bool             AlRule_is_state();
extern Bool             AlRule_is_processing_state();
extern Bool             AlRule_is_message_property();
extern NORET            AlRule_get_field_class_names();
extern NORET            AlRule_get_processing_state_names();
extern NORET            AlRule_get_message_property_names();
extern char*            AlRule_get_field_class_default_field_type();
extern AlRFType         AlRule_get_class_from_name();
extern char*            AlRule_get_name_from_class();
extern AlRule           AlRule_create_default_rule();
#endif
/***** So Far Limitted comments ....

AlRule_create(predicate, darray-of-actions, create-time, update-time, name)
	Function takes the rules predicate as a AlRuleMember and a Darray
	of AlAction's for the actions.  For rules that are being created as
	new (as opposed to read off of disk) the create and update times can
	be suplied as (time_t)0.  If the rule already "exists" and is
	simply being created in memory its previous times should be
	suplied.  The name is optional but should be passed as (char *)NULL
	if no name.  The function returns an AlRule.

AlRule_get_actions(rule)
	Function return THE Darray of actions for the rule; so don't go
	messing with it.  Just get things from it unless you really want to
	change it.

AlRule_set_name(rule, name)
	Function sets the optional name of "rule" to "name."  It returns
	the ptr to the actual string in the AlRule structure.

AlRuleMember_mcreate_assoc(type)
	Function is passed the type of association (see the typedef for
	AlRAType).  An association member of this type is then created and
	retuned.

AlRuleMember_mcreate_field(kind, key, type, value, op)
	Function returns a rule member of type ALRMT_FIELD.  The argument
	"kind" specifies the type of field (see the typedef for ALRFType).
	The key is the key-name for the FieldCore object that the
	field member will contain.  The type is the type of field as
	FieldCore understands types (SubString, etc.).  Value is the test
	value for the field, and op is the operator for testing (suplied as
	a string).  All string values are copied.  The value is not tested
	to see that it is parsabele by the type.  To do this use 
	AlRuleField_test_contents(AlRuleField); .

AlRuleField_test_contents(field)
        returns Bool_TRUE if the field type will parse the valur for the
	field.  Bool_FALSE otherwise.

AlRuleField_get_strvalue(rule-field)
	Function returns the value of the rule-field as suplied at create
	time.  This is the unparsed value.

AlRuleField_get_op_name(rule-field)
	Function returns the name of the operator used for testing of the
	rule-field value, as suplied at create time.

***/	

#endif /* _RULE_H_ */
