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

static eps_t *eps_alloc(void);

eps_t *eps_alloc(void)
{
  eps_t *e = NULL;

  e = (eps_t *)malloc(sizeof(eps_t));
  if (e == NULL)
     return NULL;

  memset((eps_t *)e, 0, sizeof(eps_t));
  return e;
}

eps_t *eps_begin(const int interface, const void *args)
{
  int ret = 0, fd = 0;
  eps_t *e = NULL;

  e = eps_alloc();
  if (e == NULL)
     return NULL;

  e->interface = interface;

  if (interface & INTERFACE_ASYNC) {
	 if (!(interface & INTERFACE_STREAM)) {
		eps_end(e);
		return NULL;
     }
  }

  /*
     Just allow EPS calls to be made
     (this can be risky as far as stability)
  */
  if (interface == INTERFACE_NONE)
     return e;

  else if (interface & INTERFACE_STREAM) {
     ret = int_stream_init(e, (int *)args);
     if (!ret) {
        eps_end(e);
        return NULL;
     }

     return e;
  }

  else if (interface & INTERFACE_BUFFER) {
     fd = -1;

     ret = int_stream_init(e, (int *)&fd);
     if (!ret) {
        eps_end(e);
        return NULL;
     }

     ret = int_buffer_init(e, (line_t *)args);
     if (!ret) {
        eps_end(e);
        return NULL;
     }

     return e;
  }

  return NULL;  
}

void eps_restart(eps_t *e, const void *args)
{
  if (e->interface & INTERFACE_STREAM)
     int_stream_restart(e, (int *)args);

  else if (e->interface & INTERFACE_BUFFER)
     int_buffer_restart(e, (line_t *)args);

  e->content_type = CON_NONE;

  if (e->h) {
     header_kill(e->h);
     e->h = NULL;
  }

  if (e->b) {
     boundary_kill(e->b);
     e->b = NULL;
  }

  if (e->source) {
     free(e->source);
     e->source = NULL;
  }
}

header_t *eps_next_header(eps_t *e)
{
  unsigned char *l = NULL;

  l = unfold_next_line(e->u);
  if (!l)
     return NULL;
   
  if (e->h)
     header_kill(e->h);

  e->h = header_parse(l);
  email_header_internal(e);

  eps_source(e, l);

  return e->h;
}

unsigned char *eps_next_line(eps_t *e)
{
  int ret = 0;
  unsigned char *l = NULL;

  if (e->u->b->eof)
     return NULL;

  l = buffer_next_line(e->u->b);
  if (l == NULL) {
     e->u->b->eof = 1;
     return NULL;
  }

  eps_source(e, l);

  if (e->content_type & CON_MULTI) {
     if ((*l == '-') && (*(l + 1) == '-')) {
        ret = boundary_is(e, (l + 2));
        if (ret)
           return NULL;
     }
  }

  return l;
}

void eps_header_free(eps_t *e)
{
  if (e->h == NULL)
     return;

  header_kill(e->h);

  e->h = NULL;
}

void eps_end(eps_t *e)
{
  if (e->u)
     unfold_kill(e->u);

  if (e->b)
     boundary_kill(e->b);

  if (e->m)
     mime_kill(e->m);

  if (e->h)
     header_kill(e->h);

  if (e->source)
     free(e->source);

  free(e);
}

int eps_is_eof(const eps_t *e)
{
  if (e->u->b->eof)
     return 1;

  return 0;
}

int eps_source(eps_t *eps, const unsigned char *l)
{
  int len = 0;

  if (!l)
     return 0;

  len = strlen(l);

  if (eps->source)
     free(eps->source);
  
  eps->source = (char *)malloc(len + 1);
  if (eps->source == NULL)
      return 0;

  memset(eps->source, 0, len + 1);
  memcpy(eps->source, l, len);

  return 1;
}

