#include "ep_internal.h"
#include <stdlib.h>
#include <glib.h>

/*
  Please see ep_mail_driver first
*/


/*
  text/plain process, uses text driver.
*/
GList* ep_plain_process(gchar* content, GList* credentials) {
  gchar** split;
  GList* return_list;

  split = g_strsplit(content, "\n", -1);

  LG_log(ep_ctx, LG_DEBUG, "Calling ep_split_text");
  return_list = ep_split_text(split, credentials);

  g_strfreev(split);

  return return_list;
}

/*
  Processes multipart/mixed, in practice tries to
    process all parts.
*/
GList* ep_mixed_process(MM_content_t* content, GList* credentials) {
  GList* return_list;
  GList* parts;

  return_list = NULL;
  parts = content->parts;

  while (parts) {
    return_list = g_list_concat(return_list, ep_content_explode((MM_content_t*)parts->data, credentials));
    parts = parts->next;
  }

  return return_list;
}

/*
  Processes multipart/alternative, in practice
    tries to process the 1st part only.
*/
GList* ep_alternative_process(MM_content_t* content, GList* credentials) {
  GList* return_list;
  GList* parts;

  return_list = NULL;
  parts = content->parts;

  if  (parts) {
    return_list = ep_content_explode((MM_content_t*)parts->data, credentials);
  }

  return return_list;
}

/*
  Puts a mime part in 13+10 line ending format for pgp
    signature verification
*/
GString* ep_prepare_bulk(gchar* bulk) {
  GString* prepared_bulk;
  gint i;
  gchar prev;
  int len;

  len = strlen(bulk);
  prepared_bulk = g_string_new("");
  prev = 0;

  for(i=0;i<len;i++) {
    if (bulk[i]==10 && prev!=13) {
      g_string_append_c(prepared_bulk,13);
    }
    g_string_append_c(prepared_bulk, bulk[i]);
    prev = bulk[i];
  }

  return prepared_bulk;

}

//check if number of parts are correct!
/*
  Processes multipart/signed

*/
GList* ep_pgp_process(MM_content_t* content, GList* credentials) {
  gchar* bulk;
  gchar* signature;
  GString* prepared_bulk;
  KM_key_return_t* signature_status;
  GList* returned_content;

  //bulk = ((MM_content_t*)content->parts->data)->bulk_content;
  bulk = content->bulk_content;
  signature = ((MM_content_t*)content->parts->next->data)->content;

  prepared_bulk = ep_prepare_bulk(bulk);
  signature_status = KM_signature_verify(KM_PGP, prepared_bulk->str, signature);

  credentials = CR_credential_list_duplicate(credentials);
  if (KM_key_return_get_status(signature_status) == KM_OK) {
    credentials =
      g_list_append(credentials,
         CR_credential_new(CR_PGP,
                           KM_key_return_get_key_id(signature_status),
                           KM_key_return_get_signature_ok(signature_status)));
  }
  g_string_free(prepared_bulk, TRUE);
  returned_content =
    ep_content_explode((MM_content_t*)content->parts->data, credentials);
  CR_credential_list_free(credentials);
  KM_key_return_free(signature_status);

  return returned_content;
}

/*
  Processes a mail (embedded in another) message.

  content - content structure representing the... content.
  credentials - current list of credentials

  return - List of authenticated_data
 */
GList* ep_message_process(MM_content_t* content, GList* credentials) {
  MM_mail_info_t* mail;
  GList* return_list;

  mail = MM_extract_mail_info(content->content);
  
  credentials = CR_credential_list_duplicate(credentials);
  //credentials = g_list_append(credentials, CR_credential_new(CR_FROM, mail->header->from, TRUE));
  return_list = ep_content_explode(mail->content, credentials);

  CR_credential_list_free(credentials);
  MM_mail_info_free(mail);

  return return_list; 
}

/*
  Calls the appropriate function irt content type
*/
GList* ep_content_explode(MM_content_t* content, GList* credentials) {
  if (!content) {
    return NULL;
  }
  switch (content->type) {
  case MM_PLAIN:
    return ep_plain_process(content->content, credentials);
  case MM_MULTIPART_MIXED:
    return ep_mixed_process(content, credentials);
  case MM_MULTIPART_ALTERNATIVE:
    return ep_alternative_process(content, credentials);
  case MM_MULTIPART_SIGNED:
    return ep_pgp_process(content, credentials);
  case MM_MESSAGE:
    return ep_message_process(content, credentials);
  default:
    return NULL;
  }
}


/*
  This is the entry point for the mail driver

  This code can be recursive. There is a contract regarding the
  credential list: if a function wants to use it (attach it to another
  structure then it has to copy it completely - list plus credentials).

  In practice it simply calls ep_content explode appending a mail from
  credential.
*/
ep_input_structure_t* ep_mail_driver(ep_authenticated_data_t* data) {
  ep_input_structure_t* input;
  MM_mail_info_t* mail;
  GList* credentials;

  LG_log(ep_ctx, LG_DEBUG, "Creating MM mailer structure");
  mail = MM_extract_mail_info(data->data->data->str);
  input = ep_input_structure_new();
  input->mail_info = ep_mail_info_new(mail->header->from, mail->header->subject, mail->header->date, mail->header->reply_to, mail->header->cc, mail->header->message_id);
  
  input->is_mail = TRUE;
  credentials = g_list_append(NULL, CR_credential_new(CR_FROM, mail->header->from ? mail->header->from : "", TRUE));
  LG_log(ep_ctx, LG_DEBUG, "Exploding data");
  input->flattened_authenticated_data = ep_content_explode(mail->content, credentials);

  MM_mail_info_free(mail);

  return input; 

}


