/*
 * Copyright (c) 2002, Adam Dunkels.
 * All rights reserved. 
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution. 
 * 3. The name of the author may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.  
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 *
 * This file is part of the Contiki desktop environment for the C64.
 *
 * $Id: email.c,v 1.8 2010/05/31 15:22:08 nifi Exp $
 *
 */


#include "contiki.h"
#include "ctk/ctk.h"
#include "smtp.h"
#include "lib/petsciiconv.h"

#include "lib/ctk-textentry-multiline.h"


#include <string.h>

#ifdef EMAIL_CONF_WIDTH
#define MAIL_WIDTH EMAIL_CONF_WIDTH
#else
#define MAIL_WIDTH 37
#endif

#ifdef EMAIL_CONF_HEIGHT
#define MAIL_HEIGHT EMAIL_CONF_HEIGHT
#else
#define MAIL_HEIGHT 17
#endif

#ifdef EMAIL_CONF_ERASE
#define MAIL_ERASE EMAIL_CONF_ERASE
#else
#define MAIL_ERASE 1
#endif

#if (MAIL_WIDTH - 9) < 39
#define TEXTENTRY_WIDTH (MAIL_WIDTH - 9)
#else
#define TEXTENTRY_WIDTH 39
#endif

static struct ctk_menu menu;
unsigned char menuitem_compose, menuitem_setup, menuitem_quit;

/* The main window. */
static struct ctk_window composewindow;

static struct ctk_separator sep1 =
 {CTK_SEPARATOR(0, MAIL_HEIGHT + 3, MAIL_WIDTH + 1)};
static struct ctk_label statuslabel =
 {CTK_LABEL(7, MAIL_HEIGHT + 4, MAIL_WIDTH - 14, 1, "")};


static struct ctk_label tolabel =
  {CTK_LABEL(0, 0, 3, 1, "To:")};
static char to[40];
static struct ctk_textentry totextentry =
  {CTK_TEXTENTRY(8, 0, TEXTENTRY_WIDTH, 1, to, 39)};

static struct ctk_label cclabel =
  {CTK_LABEL(0, 1, 3, 1, "Cc:")};
static char cc[40];
static struct ctk_textentry cctextentry =
  {CTK_TEXTENTRY(8, 1, TEXTENTRY_WIDTH, 1, cc, 39)};

static struct ctk_label subjectlabel =
  {CTK_LABEL(0, 2, 8, 1, "Subject:")};
static char subject[40];
static struct ctk_textentry subjecttextentry =
  {CTK_TEXTENTRY(8, 2, TEXTENTRY_WIDTH, 1, subject, 39)};

static char mail[MAIL_WIDTH * MAIL_HEIGHT];
struct ctk_textentry mailtextentry =
  {CTK_TEXTENTRY_INPUT(0, 3, MAIL_WIDTH - 1, MAIL_HEIGHT, mail, MAIL_WIDTH - 1, \
		       ctk_textentry_multiline_input)};

static struct ctk_button sendbutton =
  {CTK_BUTTON(0, MAIL_HEIGHT + 4, 4, "Send")};

#if MAIL_ERASE
static struct ctk_button erasebutton =
  {CTK_BUTTON(MAIL_WIDTH - 6, MAIL_HEIGHT + 4, 5, "Erase")};

/* The "Really erase message?" dialog. */
static struct ctk_window erasedialog;
static struct ctk_label erasedialoglabel1 =
  {CTK_LABEL(2, 1, 22, 1, "Really erase message?")};
static struct ctk_label erasedialoglabel2 =
  {CTK_LABEL(0, 2, 26, 1, "All contents will be lost.")};
static struct ctk_button eraseyesbutton =
  {CTK_BUTTON(4, 4, 3, "Yes")};
static struct ctk_button erasenobutton =
  {CTK_BUTTON(18, 4, 2, "No")};
#endif /* MAIL_ERASE */

/* The setup window. */
static struct ctk_window setupwindow;
static struct ctk_label fromaddresslabel =
  {CTK_LABEL(0, 0, 25, 1, "Name and e-mail address")};
static char fromaddress[40];
static struct ctk_textentry fromaddresstextentry =
  {CTK_TEXTENTRY(0, 1, 26, 1, fromaddress, 39)};

static struct ctk_label smtpserverlabel =
  {CTK_LABEL(0, 3, 20, 1, "Outgoing mailserver")};
static char smtpserver[40];
static struct ctk_textentry smtpservertextentry =
  {CTK_TEXTENTRY(0, 4, 26, 1, smtpserver, 39)};

/*
static struct ctk_label pop3serverlabel =
  {CTK_LABEL(0, 6, 20, 1, "Incoming mailserver")};
static char pop3server[40];
static struct ctk_textentry pop3servertextentry =
  {CTK_TEXTENTRY(0, 7, 26, 1, pop3server, 39)};
*/

/*
static struct ctk_label pop3userlabel =
  {CTK_LABEL(0, 9, 20, 1, "Mailserver username")};
static char pop3user[40];
static struct ctk_textentry pop3usertextentry =
  {CTK_TEXTENTRY(0, 10, 26, 1, pop3user, 39)};
*/

/*
static struct ctk_label pop3passwordlabel =
  {CTK_LABEL(0, 12, 20, 1, "Mailserver password")};
static char pop3password[40];
static struct ctk_textentry pop3passwordtextentry =
  {CTK_TEXTENTRY(0, 13, 26, 1, pop3password, 39)};
*/

static struct ctk_button setupokbutton =
/*  {CTK_BUTTON(24, 15, 2, "Ok")};*/
  {CTK_BUTTON(24, 6, 2, "Ok")};

PROCESS(email_process, "E-mail client");

AUTOSTART_PROCESSES(&email_process);

/*-----------------------------------------------------------------------------------*/
static void
email_quit(void)
{
  ctk_window_close(&setupwindow);
  ctk_window_close(&composewindow);
  ctk_menu_remove(&menu);
  process_exit(&email_process);
  LOADER_UNLOAD();
}
/*-----------------------------------------------------------------------------------*/
static void
applyconfig(void)
{
  uip_ipaddr_t addr;
  uip_ipaddr_t *addrptr;
  char *cptr;

  for(cptr = smtpserver; *cptr != ' ' && *cptr != 0; ++cptr);
  *cptr = 0;
  
  addrptr = &addr;
#if UIP_UDP
  if(uiplib_ipaddrconv(smtpserver, &addr) == 0) {
    addrptr = resolv_lookup(smtpserver);
    if(addrptr == NULL) {
      resolv_query(smtpserver);
      ctk_label_set_text(&statuslabel, "Resolving host...");
      return;
    }
  }
#else /* UIP_UDP */
  uiplib_ipaddrconv(smtpserver, &addr);
#endif /* UIP_UDP */
  smtp_configure("contiki", addrptr);

  petsciiconv_toascii(fromaddress, sizeof(fromaddress));
}
/*-----------------------------------------------------------------------------------*/
static void
prepare_message(void)
{
  /* Convert fields to ASCII. */
  petsciiconv_toascii(to, sizeof(to));
  petsciiconv_toascii(cc, sizeof(cc));
  petsciiconv_toascii(subject, sizeof(subject));  
  petsciiconv_toascii(mail, sizeof(mail));
}
/*-----------------------------------------------------------------------------------*/
static void
erase_message(void)
{
  CTK_TEXTENTRY_CLEAR(&totextentry);
  CTK_TEXTENTRY_CLEAR(&cctextentry);
  CTK_TEXTENTRY_CLEAR(&subjecttextentry);
  CTK_TEXTENTRY_CLEAR(&mailtextentry);
}
/*-----------------------------------------------------------------------------------*/
PROCESS_THREAD(email_process, ev, data)
{
  struct ctk_widget *w;

  PROCESS_BEGIN();
  
#if MAIL_ERASE
  /* Create the "Really erase message?" dialog. */
  ctk_dialog_new(&erasedialog, 26, 6);
  CTK_WIDGET_ADD(&erasedialog, &erasedialoglabel1);
  CTK_WIDGET_ADD(&erasedialog, &erasedialoglabel2);
  CTK_WIDGET_ADD(&erasedialog, &eraseyesbutton);
  CTK_WIDGET_ADD(&erasedialog, &erasenobutton);
  CTK_WIDGET_FOCUS(&erasedialog, &erasenobutton);
#endif /* MAIL_ERASE */
  
  /* Create setup window. */
/*  ctk_window_new(&setupwindow, 28, 16, "E-mail setup");*/
  ctk_window_new(&setupwindow, 28, 7, "E-mail setup");
  
  CTK_WIDGET_ADD(&setupwindow, &fromaddresslabel);
  CTK_WIDGET_ADD(&setupwindow, &fromaddresstextentry);
  CTK_WIDGET_ADD(&setupwindow, &smtpserverlabel);
  CTK_WIDGET_ADD(&setupwindow, &smtpservertextentry);
/*  CTK_WIDGET_ADD(&setupwindow, &pop3serverlabel);*/
/*  CTK_WIDGET_ADD(&setupwindow, &pop3servertextentry);*/
/*  CTK_WIDGET_ADD(&setupwindow, &pop3userlabel);*/
/*  CTK_WIDGET_ADD(&setupwindow, &pop3usertextentry);*/
/*  CTK_WIDGET_ADD(&setupwindow, &pop3passwordlabel);*/
/*  CTK_WIDGET_ADD(&setupwindow, &pop3passwordtextentry);*/
  CTK_WIDGET_ADD(&setupwindow, &setupokbutton);
  
  CTK_WIDGET_FOCUS(&setupwindow, &fromaddresstextentry);
  
  
  /* Create compose window. */
  ctk_window_new(&composewindow, MAIL_WIDTH + 1, MAIL_HEIGHT + 5, "Compose e-mail");
  
  CTK_WIDGET_ADD(&composewindow, &tolabel);
  CTK_WIDGET_ADD(&composewindow, &cclabel);
  CTK_WIDGET_ADD(&composewindow, &subjectlabel);
  
  CTK_WIDGET_ADD(&composewindow, &totextentry);
  CTK_WIDGET_FOCUS(&composewindow, &totextentry);  
  CTK_WIDGET_ADD(&composewindow, &cctextentry);  
  CTK_WIDGET_ADD(&composewindow, &subjecttextentry);
  
  CTK_WIDGET_ADD(&composewindow, &mailtextentry);
  
  CTK_WIDGET_ADD(&composewindow, &sep1);
  CTK_WIDGET_ADD(&composewindow, &statuslabel);
  
  CTK_WIDGET_ADD(&composewindow, &sendbutton);
#if MAIL_ERASE
  CTK_WIDGET_ADD(&composewindow, &erasebutton);
#endif /* MAIL_ERASE */

  erase_message();
  
  /* Create and add the menu */
  ctk_menu_new(&menu, "E-mail");
  menuitem_setup = ctk_menuitem_add(&menu, "Setup");
  menuitem_compose = ctk_menuitem_add(&menu, "Compose");
  menuitem_quit = ctk_menuitem_add(&menu, "Quit");
  ctk_menu_add(&menu);
  
  /* Open setup window */
  ctk_window_open(&setupwindow);

  while(1) {

    PROCESS_WAIT_EVENT();
    
    if(ev == tcpip_event) {
      smtp_appcall(data);      
    } else if(ev == ctk_signal_widget_activate) {
      w = (struct ctk_widget *)data;
      if(w == (struct ctk_widget *)&sendbutton) {
	prepare_message();
	smtp_send(to, cc, fromaddress, subject, mail, MAIL_WIDTH, MAIL_HEIGHT);
	ctk_label_set_text(&statuslabel, "Sending message...");
	CTK_WIDGET_REDRAW(&statuslabel);
#if MAIL_ERASE
      } else if(w == (struct ctk_widget *)&erasebutton) {
	ctk_dialog_open(&erasedialog);      
      } else if(w == (struct ctk_widget *)&eraseyesbutton) {
	erase_message();
	ctk_dialog_close();
      } else if(w == (struct ctk_widget *)&erasenobutton) {
	ctk_dialog_close();
#endif /* MAIL_ERASE */
      } else if(w == (struct ctk_widget *)&setupokbutton) {
	applyconfig();
	ctk_window_close(&setupwindow);
	ctk_window_open(&composewindow);
      }
    } else if(ev == ctk_signal_menu_activate) {
      if((struct ctk_menu *)data == &menu) {
	if(menu.active == menuitem_compose) {
	  ctk_window_open(&composewindow);
	} else if(menu.active == menuitem_setup) {
	  ctk_window_open(&setupwindow);
	} else if(menu.active == menuitem_quit) {
	  email_quit();
	}
      }
#if UIP_UDP
    } else if(ev == resolv_event_found) {
      if(strcmp(data, smtpserver) == 0) {
	if(resolv_lookup(smtpserver) != NULL) {
	  applyconfig();
	  ctk_label_set_text(&statuslabel, "");
	} else {
	  ctk_label_set_text(&statuslabel, "Host not found");
	}
	CTK_WIDGET_REDRAW(&statuslabel);  
      }
#endif /* UIP_UDP */
    } else if(ev == PROCESS_EVENT_EXIT) {
      email_quit();
    }
  }
  PROCESS_END();
}
/*-----------------------------------------------------------------------------------*/
void
smtp_done(unsigned char error)
{
  if(error == SMTP_ERR_OK) {
    ctk_label_set_text(&statuslabel, "Mail sent");
    erase_message();
    ctk_window_open(&composewindow);
  } else {
    ctk_label_set_text(&statuslabel, "Mail error");
  }
  CTK_WIDGET_REDRAW(&statuslabel);  
}
/*-----------------------------------------------------------------------------------*/
