#include <sys/types.h>
#include <time.h>
#include <regex.h>

#define LINE 1024
#define DEBUG 0
#define REPLACESTR "___"

typedef struct _oak_list {
  int size;
  int avail;
  void **list;
} oak_list;

typedef struct _oak_fire {
  time_t next;       /* the unix time at which to fire next */
  time_t interval;   /* the number of seconds between intervals */
} oak_fire;


typedef struct _oak_queue {
  char *name;
  char **msgs;
  char **host;
  int *msgcount;
  int nummsgs;
  oak_fire *fire;
  oak_list *actionlist;
  int locktime;
  char *header;
  int trashqueue;
  int prescan;
} oak_queue;

typedef struct _oak_action {
  char *name;
  int argc;
  char **argv;
  int haslimits;
  int limit_lines;
  int limit_linelen;
  int limit_numhosts;
  int limit_hostents;
} oak_action;


typedef oak_list oak_matchlist;
typedef oak_list oak_queuelist;
typedef oak_list oak_timelist;

typedef struct _oak_matchline {
  regex_t regex;
  oak_queuelist ql;
  oak_queuelist locked_queuelist;
  oak_timelist  lock_times;
} oak_matchline;

typedef struct _oak_global {
  char logfile[1024];
  oak_queuelist queuelist;
  oak_matchlist matchlist;
  int nukepid;
  int nukeciscopid;
  int onlyhosts;
  int ignorehosts;
  oak_list hostlist;
  int hostsort;
  oak_list hostsortlist;
} oak_global;

oak_global g;

/* -------------------------------- action.c -------------------------------- */
oak_action *action_create(char *name, int argc, char **argv);
oak_action *action_create_from_argstring(char *name, char *args);
void action_set_limits(oak_action *act, int lines, int linelen, int numhosts, int hostents);
void action_execute(oak_action *act, oak_queue *q);
char *action_get_name(oak_action *act);

/* -------------------------------- fire.c -------------------------------- */
oak_fire *fire_create(char *in);
int fire_is_time(oak_fire *f);

/* -------------------------------- global.c -------------------------------- */
void oak_global_init(oak_global *g);
char *oak_global_get_logfile(oak_global *g);
void oak_global_set_logfile(oak_global *g, char *filename);
oak_queuelist *oak_global_get_queuelist(oak_global *g);
void oak_global_set_queuelist(oak_global *g, oak_queuelist *ql);
oak_matchlist *oak_global_get_matchlist(oak_global *g);
void oak_global_set_matchlist(oak_global *g, oak_matchlist *ml);
int oak_global_is_nukepid(oak_global *g);
void oak_global_set_nukepid(oak_global *g);
void oak_global_set_no_nukepid(oak_global *g);
int oak_global_is_nukeciscopid(oak_global *g);
void oak_global_set_nukeciscopid(oak_global *g);
void oak_global_set_no_nukeciscopid(oak_global *g);
int oak_global_host_is_ok(oak_global *g, char *host);
int oak_global_set_ignorehosts(oak_global *g, char *hosts);
int oak_global_set_onlyhosts(oak_global *g, char *hosts);
void _oak_global_set_hostlist(oak_global *g, char *hosts);

/* -------------------------------- list.c -------------------------------- */
int oak_list_create(oak_list *l);
int oak_list_get_size(oak_list *l);
void *oak_list_get_element(oak_list *l, int n);
int oak_list_append_element(oak_list *l, void *element);
int oak_list_remove_element(oak_list *l, int n);
void oak_list_free_all(oak_list *l, void (*elefree)(void *));
void oak_list_free_simple(oak_list *l);

/* -------------------------------- matchline.c -------------------------------- */
oak_matchline *matchline_create(char *regex, char *queuenames);
void matchline_set_queuelist(oak_matchline *m, oak_queuelist *ql);
int matchline_set_queuelist_from_string(oak_matchline *m, char *queuenames);
int matchline_string_matches(oak_matchline *m, char *instr, char *out, int nukepid, int nukeciscopid);
oak_queuelist *matchline_get_queuelist(oak_matchline *m);
int matchline_locked_for_queue(oak_matchline *m, oak_queue *q);
void matchline_set_lock(oak_matchline *m, oak_queue *q);

/* -------------------------------- oak.c -------------------------------- */
int main(int argc, char **argv);
void readconfig(char *file);
char *get_line_from_log(char *log);
char *get_host_from_log(char *log);
void print_usage(int err);

/* -------------------------------- queue.c -------------------------------- */
oak_queue *queue_create(char *name, oak_list *actionlist, oak_fire *fire);
char *queue_get_name(oak_queue *q);
int queue_is_prescan(oak_queue *q);
void queue_set_prescan(oak_queue *q);
int queue_get_nummsgs(oak_queue *q);
char *queue_get_msg_n(oak_queue *q, int n);
char *queue_get_host_n(oak_queue *q, int n);
int queue_get_msgcount_n(oak_queue *q, int n);
void queue_set_header(oak_queue *q, char *header);
char *queue_get_header(oak_queue *q);
int queue_is_locking(oak_queue *q);
void queue_set_locktime_fromstring(oak_queue *q, char *in);
int queue_get_locktime(oak_queue *q);
void queue_add_msg(oak_queue *q, char *msg, char *host);
void queue_delete_msgs(oak_queue *q);
oak_fire *queue_get_fire(oak_queue *q);
oak_list *queue_get_actionlist(oak_queue *q);
void queue_set_fire(oak_queue *q, oak_fire *fire);
void queue_set_actionlist(oak_queue *q, oak_list *actionlist);
char *queue_to_string(oak_queue *q);
char *queue_to_string_truncate(oak_queue *q, int lines, int linelen, int numhosts, int hostents);

/* -------------------------------- queuelist.c -------------------------------- */
oak_queue *queuelist_get_queue_by_name(oak_queuelist *ql, char *name);

/* -------------------------------- timelist.c -------------------------------- */
oak_timelist *timelist_append_time(oak_timelist *a, time_t *t);
int timelist_get_num_times(oak_timelist *tl);
time_t *timelist_get_time_n(oak_timelist *tl, int n);
oak_timelist *timelist_remove_time_n(oak_timelist *tl, int n);

/* -------------------------------- util.c -------------------------------- */
int trim_string_by_lines(char *instr, char *outstr, int lines);
void replace_string_sections(char *in, regmatch_t pmatch[], char *out, char *newstr);
char **argstring_to_argv(char *in, int *outargc);

/* -------------------------------- zephyr.c -------------------------------- */
void send_zephyr(char *class, char *instance, char *recipient, char *message, char *opcode, char *zsig);
