#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#include <sys/types.h>
#include <time.h>
#include "oak.h"

oak_matchline *matchline_create(char *regex, char *queuenames) {
  oak_matchline *out;
  int ret;
  char buff[LINE];
  char *ptr, *ptr2;
  
  out=malloc(sizeof(oak_matchline));
  ret=regcomp(&(out->regex), regex, REG_EXTENDED);
  if (ret) {
    regerror(ret, NULL, buff, LINE);
    fprintf(stderr, buff);
    fprintf(stderr, "\n");
    exit(1);
  }
  oak_list_create(&(out->ql));
  
  /* do the queues here */
  if (queuenames) {
    printf("%s\n", queuenames);
    ptr=strdup(queuenames);
    ptr2=strtok(ptr, " \r\n");
    if (DEBUG) printf("DEBUG: added queue '%s' to matchline\n", ptr2);
    oak_list_append_element(&(out->ql), queuelist_get_queue_by_name(oak_global_get_queuelist(&g), ptr2));
    while ((ptr2=strtok(NULL, " \r\n"))!=NULL) {
      if (DEBUG) printf("DEBUG: added queue '%s' to matchline\n", ptr2);
      oak_list_append_element(&(out->ql), queuelist_get_queue_by_name(oak_global_get_queuelist(&g), ptr2));
    }
  }

  oak_list_create(&(out->locked_queuelist));
  oak_list_create(&(out->lock_times));

  return(out);
}


int matchline_set_queuelist_from_string(oak_matchline *m, char *queuenames) {
  char *ptr, *ptr2;
  oak_queue *q;

  oak_list_create(&(m->ql));

  ptr=strdup(queuenames);
  ptr2=strtok(ptr, " \r\n");
  q=queuelist_get_queue_by_name(oak_global_get_queuelist(&g), ptr2);
  if (q==NULL) return(-1);

  if (DEBUG) printf("DEBUG: adding queue '%s' to matchline\n", ptr2);
  oak_list_append_element(&(m->ql), q);
  while ((ptr2=strtok(NULL, " \r\n"))!=NULL) {
    q=queuelist_get_queue_by_name(oak_global_get_queuelist(&g), ptr2);
    if (q==NULL) return(-1);
    
    if (DEBUG) printf("DEBUG: adding queue '%s' to matchline\n", ptr2);
    oak_list_append_element(&(m->ql), q);
  }
  return(0);
}
												   

int matchline_string_matches(oak_matchline *m, char *instr, char *out, int nukepid, int nukeciscopid) {
  /* get the 'line' part of instr.  if it matches the regex then
     return 1, otherwise return 0.  The matched string will be
     returned in out except that anything in parens in the regex will
     be replaced with ___ */
  int ret;
  regmatch_t pmatch[15];
  char *tmpstr, *foostr;

  tmpstr=get_line_from_log(instr);
  foostr=malloc(strlen(tmpstr)+20);

  /* replace pid's if we're supposed to */
  if (nukepid) {
    regex_t regex;
    
    ret=regcomp(&regex, "^.+\\[(.+)\\]:", REG_EXTENDED);
    if (ret) {
      /* regerror(ret, NULL, buff, LINE); */
      /* we can't really syslog, but don't do this  */
    }
    
    ret=regexec(&regex, tmpstr, 15, pmatch, NULL);
    regfree(&regex);
    if (!ret) {
      replace_string_sections(tmpstr, pmatch, foostr, REPLACESTR);
      strcpy(tmpstr, foostr);
    }
  }

  /* and cisco ones too */
  if (nukeciscopid) {
    regex_t regex;
    
    ret=regcomp(&regex, "^([0-9]+):(.*):? %", REG_EXTENDED);
    if (ret) {
      /* regerror(ret, NULL, buff, LINE); */
      /* we can't really syslog, but don't do this  */
    }
    
    ret=regexec(&regex, tmpstr, 15, pmatch, NULL);
    regfree(&regex);
    if (!ret) {
      replace_string_sections(tmpstr, pmatch, foostr, REPLACESTR);
      strcpy(tmpstr, foostr);
    }
  }

  /* check for a match */
  ret=regexec(&(m->regex), tmpstr, 15, pmatch, NULL);
  if (ret) {
    strcpy(out, ""); /* not really necessary */
    free(tmpstr);
    free(foostr);
    return(0);
  }

  /* replace text if necessary */
  replace_string_sections(tmpstr, pmatch, out, REPLACESTR);
  free(tmpstr);
  free(foostr);

  return(1);
}

oak_queuelist *matchline_get_queuelist(oak_matchline *m) {
  /* return the queuelist associated with the matchline m */
  return(&(m->ql));
}

int matchline_locked_for_queue(oak_matchline *m, oak_queue *q) {
  /* if not do the clean up */
  int i, num;
  oak_queue *tmpq;
  time_t *tmptime;
  

  num=oak_list_get_size(&(m->locked_queuelist));
  for (i=0; i<num; i++) {
    tmpq=oak_list_get_element(&(m->locked_queuelist), i);
    if (tmpq != q) continue;

    tmptime=oak_list_get_element(&(m->lock_times), i);
    /* if the time is not up then it's locked, return 1 */
    if (*tmptime > time(NULL)) return(1);

    /* otherwise the lock has expired, we need to clean it up and then return 0 */
    oak_list_remove_element((&m->locked_queuelist), i);
    oak_list_remove_element(&(m->lock_times), i);
    free(tmptime);

    return(0);
  }

  /* never heard of that queue */
  return(0);
}

void matchline_set_lock(oak_matchline *m, oak_queue *q) {
  time_t *tmptime;
  time_t foo;
  
  if (matchline_locked_for_queue(m, q)) {
    /* hrm, update the time probably, don't worry about it for now */
    return;
  }

  foo=time(NULL) + queue_get_locktime(q);
  tmptime=malloc(sizeof(time_t));
  memcpy(tmptime, &foo, sizeof(time_t));

  oak_list_append_element(&(m->locked_queuelist), q);
  oak_list_append_element(&(m->lock_times), tmptime);
}
