#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "eps.h"

static void address_fixup(address_t *);

group_t *address_evaluate(const char *data)
{
  group_t *g = NULL;
  char *d = NULL, *h = NULL, *t = NULL;
  address_t *alist = NULL, *a = NULL, *a_tail = NULL;

  g = (group_t *)malloc(sizeof(group_t));
  if (g == NULL)
     return NULL;

  alist = (address_t *)malloc(sizeof(address_t));
  if (alist == NULL) {
     free(g);
     return NULL;
  }

  a_tail = alist;
  alist->next = NULL;
  g->group = NULL;
  g->members = a_tail;
  g->nmembers = 0;

  /*
     address_evaluate_one mangles data
  */
  d = mstrdup((char *)data);
  if (d == NULL) {
     free(g);
     free(alist);
     return NULL;
  }

  t = d;
  h = rfc2822_next_token(d, ':', "<>;");
  if (*h == ':') {
     *h++ = '\0';

     g->group = mstrdup(t);

     while((*h == ' ') || (*h == '\t'))
       h++;

     t = h;
  }

  else
    h = t = d;

  while(1) {
    h = rfc2822_next_token(t, ',', NULL);
    if (!(*h))
       break;

    *h = '\0';

    a = address_evaluate_one(t);
    if (!a)
       break;

    a_tail->next = a;
    a->next = NULL;
    a_tail = a;
    g->nmembers++;
 
    t = (h + 1);
  }

  if (*t) {
     a = address_evaluate_one(t);
     if (a) {
        a_tail->next = a;
        a->next = NULL;
        a_tail = a;
        g->nmembers++;
     }
  }

  if (g->group) {
     h = rfc2822_convert_literals(g->group);
     free(g->group);
     g->group = h;
  }

  free(d);
  return g;
}

address_t *address_evaluate_one(char *data)
{
  address_t *a = NULL;
  char *p = NULL, *n = NULL, *u = NULL, *h = NULL, *d = NULL;

  n = u = d = NULL;

  a = (address_t *)malloc(sizeof(address_t));
  if (a == NULL)
     return NULL;

  memset((address_t *)a, 0, sizeof(address_t));

  p = data;

  /*
     Name/User
  */
  h = rfc2822_next_token(data, '<', NULL);
  if (*h == '<') {
     *h++ = '\0';

     if (*p)
        n = data;

     if (*h)
        u = h;
     else
        return a;

     for (p = (h - 2); ((p > data) && ((*p == ' ') || (*p == '\t'))); p--);
     *(++p) = '\0';
     p = h;

     if ((n) && (*n))
        a->name = mstrdup(n);
  }

  /*
     User/Domain
  */
  h = rfc2822_next_token(p, '@', ">");
  if (*h == '@') {
     *h++ = '\0';
     if (!(*h))
        return a;

     if (!u) {
        while((*p == ' ') || (*p == '\t'))
          p++;

        u = p;
     }

     d = p = h;     
  }

  else
     return a;

  a->user = mstrdup(u);

  /*
     End
  */
  h = rfc2822_next_token(p, '>', " ");
  if (*h == '>')
     *h = '\0';

  a->domain = mstrdup(d);

  address_fixup(a);
  
  return a;
}

void address_kill(group_t *g)
{
  address_t *a = NULL, *ao = NULL;

  if (g->members) {
     a = g->members;
     while(a->next) {
       ao = a->next;
       a->next = a->next->next;

       address_kill_one(ao);
     }

     free(g->members);
  }

  free(g);
}

void address_kill_one(address_t *a)
{
  if (!a)
     return;

  if (a->name)
     free(a->name);

  if (a->user)
     free(a->user);

  if (a->domain)
     free(a->domain);

  free(a);
}

void address_fixup(address_t *a)
{
  char *p = NULL;

  if (!a)
     return;

  if (a->name) {
     p = rfc2822_convert_literals(a->name);
     free(a->name);
     a->name = p;
  }
}

