#include "emil.h"

struct message *
fix_structure(struct message *m)
{
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+ fix_structure\n");
#endif
  if (m == NULL)
    return(NULL);
  m->sd = m->sdl;
  m->td = m->sd;
  if (m->sdl->next)
    m = split_into_messages(m);
  if (m->child)
    m->child = fix_structure(m->child);
  if (m->sibling)
    m->sibling = fix_structure(m->sibling);
  return(m);
}
struct message *
split_into_messages(struct message *m)
{
  struct message *nm;
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+   split_in_message\n");
#endif
  nm = (struct message *)copy_mstruct(m, 1);
  if (m->level == 0)
    {
      nm->h = m->h;
      m->h = NULL;
    }
  nm->level = m->level;
  m->level += 1;
  nm->parent = m->parent;
  nm->sdl->encoding = EMULTI;
  nm->sdl->type = NEWSTR("MULTIPART");
  m->parent = nm;
  nm->child = split_data_list(m);
  return(nm);
}

struct message *
split_data_list(struct message *m)
{
  struct message *nm;
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+   split_data_list\n");
#endif
  if (m->sd != NULL && m->td != NULL)
    {
      m->sdl = m->sd;
      nm = (struct message *)copy_mstruct(m, 2);
      nm->parent = m->parent;
      nm->level = m->level;
      nm->sd = m->sd->next;
      nm->td = m->td->next;
      m->sd->next = NULL;
      m->td->next = NULL;
      m->sibling = split_data_list(nm);
      return(m);
    }
  else
    return(NULL);
}

struct message *
collapse_message(struct message *m)
{
  struct message *nm;
  struct data *last = NULL;
  struct data *first = NULL;
  
  first = m->sd;
  if ((last = m->sd) != NULL)
    while (last->next != NULL)
      last = last->next;
  if ((nm = (struct message *)m->child) != NULL)
    m->sd = collapse_data(first, last, nm);
  return(m);
}

struct data *
collapse_data(struct data *first, struct data *last, struct message *m)
{
  struct data *tmp;

  if ((tmp = m->sd) != NULL)
    {
      if (last == NULL)
	{
	  first = tmp;
	  last = tmp;
	}
      else
	last->next = tmp;
      while (last->next != NULL)
	last = last->next;
    }
  if (m->child != NULL)
    last = collapse_data(first, last, m);
  if (m->sibling != NULL)
    last = collapse_data(first, last, m);
  return(first);
}

void
multimize(struct message *m, int number)
{
  struct message *h, *l, *t;
  int children;
  h = (struct message *)Yalloc(sizeof(struct message));
  h->sd = m->sd;
  m->sd = NULL;
  h->td = m->td;
  m->td = NULL;
  h->sdl = m->sdl;
  m->sdl = NULL;
  h->tdl = m->tdl;
  m->tdl = NULL;
  h->level = m->level + 1;
  l = m->child = h;
  t = m->sibling;
  m->sibling = NULL;
  children = 1;
  for (t = m->sibling; t != NULL && children <= number; t = t->sibling,
       children++)
    {
      l->sibling = t;
      l = l->sibling;
    }
  m->children = children;
  
}
