/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.core.internals;

import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.svc.GlobalSite;
import com.silverwrist.venice.util.MailSend;

class BaseMailSend implements MailSend
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static final InternetAddress[] ADDR_TEMPLATE = new InternetAddress[0];
  private static final Message.RecipientType[] TYPE_VALS =
      { Message.RecipientType.TO, Message.RecipientType.CC, Message.RecipientType.BCC };

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private GlobalSite site;           // the global site
  private Session session;           // the email session
  private MimeMessage msg;           // the message being composed
  private ArrayList[] recips;        // lists of recipients
  private String subject = null;     // subject string
  private String text = null;        // text string
  private HashMap variables = null;  // substitution variables for subject and text

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  BaseMailSend(GlobalSite site, Properties props, javax.mail.Session session)
  {
    this.site = site;
    this.session = session;
    msg = new MimeMessage(session);
    try
    { // set the X-Mailer header
      msg.setHeader("X-Mailer",(String)(props.get("com.silverwrist.venice.email.mailer")));

    } // end try
    catch (Exception e)
    { // do nothing - we don't really care about this too much
    } // end catch

    try
    { // set the From address on the message
      msg.setFrom(InternetAddress.getLocalAddress(session));

    } // end try
    catch (MessagingException me)
    { // this should be impossible
      throw new InternalStateError("condition should not apply to message here",me);

    } // end catch

    recips = new ArrayList[3];
    recips[0] = recips[1] = recips[2] = null;

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Implementations from interface MailSend
   *--------------------------------------------------------------------------------
   */

  public void addRecipient(int type, String addr) throws EmailException
  {
    if ((type<0) || (type>=recips.length))
      throw new IndexOutOfBoundsException("invalid recipient type");

    try
    { // create an Internet address and set the recipient to it
      InternetAddress address = new InternetAddress(addr);
      if (recips[type]==null)
	recips[type] = new ArrayList();
      recips[type].add(address);

    } // end try
    catch (AddressException e1)
    { // the address was somehow invalid
      throw new EmailException("invalid email recipient address",e1);

    } // end catch

  } // end addRecipient

  public void removeRecipient(int type, String addr) throws EmailException
  {
    if ((type<0) || (type>=recips.length))
      throw new IndexOutOfBoundsException("invalid recipient type");

    if (recips[type]==null)
      return;  // nothing there

    for (int i=0; i<recips[type].size(); i++)
    { // check out each address
      InternetAddress a = (InternetAddress)(recips[type].get(i));
      if (addr.equalsIgnoreCase(a.getAddress()))
      { // remove the address!
	recips[type].remove(i);
	break;

      } // end if

    } // end for

  } // end removeRecipient

  public void clearRecipients(int type)
  {
    if ((type<0) || (type>=recips.length))
      throw new IndexOutOfBoundsException("invalid recipient type");

    if (recips[type]!=null)
      recips[type].clear();

  } // end clearRecipients

  public void setFrom(String from_name, String from_addr) throws EmailException
  {
    try
    { // set the "from" address
      InternetAddress addr = new InternetAddress(from_addr);
      addr.setPersonal(from_name);
      msg.setFrom(addr);

      // make sure the "Sender" address reflects our email address
      InternetAddress sender = InternetAddress.getLocalAddress(session);
      msg.setHeader("Sender",sender.toString());

    } // end try
    catch (AddressException e1)
    { // the address was somehow invalid
      throw new EmailException("invalid email sender address",e1);

    } // end catch
    catch (MessagingException e2)
    { // msg.setRecipients should NOT be throwing a MessageException here!
      throw new InternalStateError("condition should not apply to message here",e2);

    } // end catch
    catch (java.io.UnsupportedEncodingException e3)
    { // we can't really have that happen here, either!
      throw new InternalStateError("condition should not apply to message here",e3);
      
    } // end catch

  } // end setFrom

  public void setSubject(String subject)
  {
    this.subject = subject;

  } // end setSubject

  public void setStockSubject(String identifier)
  {
    this.subject = site.getStockMessage(identifier);

  } // end setStockSubject

  public void setText(String text)
  {
    this.text = text;

  } // end setStockText

  public void setStockText(String identifier)
  {
    this.text = site.getStockMessage(identifier);

  } // end setStockText

  public void setVariable(String name, String value)
  {
    if (variables==null)
      variables = new HashMap();
    if (value==null)
      variables.remove(name);
    else
      variables.put(name,value);

  } // end setVariable

  public void addHeader(String name, String value)
  {
    try
    { // pass through 
      msg.addHeader(name,value);

    } // end try
    catch (MessagingException me)
    { // this should be impossible
      throw new InternalStateError("condition should not apply to message here",me);

    } // end catch

  } // end addHeader

  public void removeHeader(String name)
  {
    try
    { // pass through 
      msg.removeHeader(name);

    } // end try
    catch (MessagingException me)
    { // this should be impossible
      throw new InternalStateError("condition should not apply to message here",me);

    } // end catch

  } // end removeHeader

  public void send() throws EmailException
  {
    try
    { // set the recipient addresses
      for (int i=0; i<recips.length; i++)
      { // load each set of addresses into the message
	if ((recips[i]!=null) && !(recips[i].isEmpty()))
	{ // retrieve the address list and save it off
	  InternetAddress[] addrlist = (InternetAddress[])(recips[i].toArray(ADDR_TEMPLATE));
	  msg.setRecipients(TYPE_VALS[i],addrlist);

	} // end if
        else  // null out these addresses
	  msg.setRecipients(TYPE_VALS[i],ADDR_TEMPLATE);

      } // end for
	  
      if (subject!=null)
      { // set the message subject
	if (variables==null)
	  msg.setSubject(subject);
	else
	  msg.setSubject(StringUtil.replaceAllVariables(subject,variables));

      } // end if

      if (text!=null)
      { // set the message subject
	if (variables==null)
	  msg.setText(text);
	else
	  msg.setText(StringUtil.replaceAllVariables(text,variables));

      } // end if

      // attempt to send the message!
      Transport.send(msg);

    } // end try
    catch (SendFailedException e1)
    { // convert this exception into an EmailException
      throw new EmailException("send of the email message failed: " + e1.getMessage(),e1);

    } // end catch
    catch (MessagingException e2)
    { // msg.setText should NOT be throwing a MessageException here!
      throw new InternalStateError("condition should not apply to message here",e2);

    } // end catch
    
  } // end send

} // end class BaseMailSend
