package oracle.forms.fd;

import java.io.*;
import java.util.*;
import oracle.forms.handler.IHandler;
import oracle.forms.properties.ID;
import oracle.forms.ui.CustomEvent;
import oracle.forms.ui.VBean;
/*
 * get the .jar file 
 * http://jakarta.apache.org/site/downloads/downloads_commons-net.cgi
 */
import org.apache.commons.net.pop3.*;

  /**
   * A javabean to query a POP3 server
   *   
   * @author   Francois Degrelle
   * @creation May 2007     
   * @version  1.0
   */


public class POP3Reader extends VBean implements Runnable
{

    public final static ID idSetLogin     = ID.registerProperty("SET_LOGIN_INFO");    
    public final static ID idClearList    = ID.registerProperty("CLEAR_LIST");
    public final static ID idSetMsg       = ID.registerProperty("SET_MESSAGE");
    public final static ID idCountMsg     = ID.registerProperty("GET_MESSAGE_COUNT");
    public final static ID idGetHead      = ID.registerProperty("GET_HEADER");
    public final static ID idGetMsg       = ID.registerProperty("GET_MESSAGE");
    public final static ID idSetMaxLength = ID.registerProperty("SET_MAX_LENGTH");
    public final static ID SEND_MSG       = ID.registerProperty("SENDMSG");
    public final static ID SEND_ERR       = ID.registerProperty("SENDERROR");    
    public final static ID MSGINFO        = ID.registerProperty("MSGINFO");
    public final static ID MSGNUM         = ID.registerProperty("MSGNUM");
    public final static ID MSGCOUNT       = ID.registerProperty("MSGCOUNT");    
    public final static ID MSGERROR       = ID.registerProperty("MSGERROR");    
    
    private String sPopName    = "" ;
    private String sUserName   = "" ;
    private String sPwd        = "" ;
    private List   lstEntries  = new ArrayList(10) ; 
    private int    iNumMessage = 0 ;
    private int    iCountMsg   = 0 ;
    private int    iMaxLength  = 32000 ;
    private IHandler     m_handler; 
    static Thread  runner ;
    
    public void init(IHandler handler)
    {
      m_handler = handler;
      super.init(handler);
    } 
    
    public boolean setProperty(ID property, Object value)
    {
      //
      // set the connction information
      // and query the POP server
      //
      if (property == idSetLogin)
      {
        System.out.println(property+":"+value);
        sPopName = "" ;
        sUserName = "" ;
        sPwd = "" ;
        String s = value.toString();
        StringTokenizer st = new StringTokenizer(s,",");
        if (st.hasMoreTokens()) sPopName  = st.nextToken() ;
        if (st.hasMoreTokens()) sUserName = st.nextToken() ;          
        if (st.hasMoreTokens()) sPwd      = st.nextToken() ;          
        if( (sPopName != null) && (sUserName != null) && (sPwd != null))
        {
            runner = new Thread(this);
            runner.start();
        }
        return true;
      }          
      // clear the list
      else if (property == idClearList)  
      {
        lstEntries  = new ArrayList(10) ;
        iCountMsg = 0 ;
        return true;
      }
      
      // Max length message to get
      else if (property == idSetMaxLength)  
       {
         System.out.println(property+":"+value);
         try {
            iMaxLength = Integer.parseInt(value.toString());
         }
         catch (Exception e) { e.printStackTrace(); }
         return true;
       }       
      
       // set the number of message to read
       else if (property == idSetMsg)  
       {
         System.out.println(property+":"+value);
         try {
            iNumMessage = Integer.parseInt(value.toString());
         }
         catch (Exception e) { e.printStackTrace(); }
         return true;
       }      
    else
     {
       return super.setProperty(property, value);
      }
    }

    //
    //  Get the properties 
    //
    public Object getProperty(ID pId)
    {
      // tooltip
      if(pId == idGetHead)
      {
         String sHeader = "" ;
         MailEntry me = (MailEntry) lstEntries.get(iNumMessage-1) ;
         sHeader = me.sSubject + "^" + me.sFrom + "^" + me.sDate ;
         return sHeader ;
      }
      else if(pId == idGetMsg)
        {
          MailEntry me = (MailEntry) lstEntries.get(iNumMessage-1) ;
          return me.sMessage ;
        }   
      // number of messages available
      else if(pId == idCountMsg)
      {
         return "" + iCountMsg ;
      }   

      else return super.getProperty(pId);
    }     

    
  // Start the thread
  public void run()
  {
   Thread theThread = Thread.currentThread();    
   while (runner == theThread)
   {
   try
   {
     POP3Client client = new POP3Client();
     System.out.println("Try connectiong to:"+sPopName+"("+sUserName+")");
     client.connect( sPopName, 110 );
     if( client.login( sUserName, sPwd ) )
     {
      System.out.println("Connected with:"+sPopName+"("+sUserName+")");
      POP3MessageInfo[] messages = client.listMessages();
      System.out.println( "Messages: " + messages.length );
      iCountMsg = messages.length ;
      // Retrieves the messages
      for( int i=0; i<messages.length; i++ ) 
      {
        System.out.println( "Message number=" + messages[i].number + 
                  ", size=" + messages[i].size );
        POP3Header header = new POP3Header( client.retrieveMessageTop( messages[ i ].number, 1 ) );
        // add to the entry list
        MailEntry me = new MailEntry(
                           i,
                           header.getFrom(),
                           header.getTo(),
                           header.getSubject(),
                           header.getDate(),
                           getMessage( client.retrieveMessage( messages[i].number ) )) ;
        lstEntries.add(me) ;
        try {
               theThread.sleep(500);
        } catch (InterruptedException e) { }
        
        SendMessage(i,"Message number=" + messages[i].number + ", size=" + messages[i].size );        
        
       }
     }
     else
     {
      System.out.println( "Login unsuccessful..." );
     }

     client.logout();
     client.disconnect();
   }
   catch( Exception e )
   {
     e.printStackTrace();
     SendMessage(-1, e.getMessage() );        
   }
    theThread = null ;
   }
  }

  /*
   *  Get the message body
   */
  String getMessage( Reader r )
  {
   try
   {
     String sMessage = "" ;
     BufferedReader br = new BufferedReader( r );
     String line = br.readLine();
     StringBuffer sb = new StringBuffer();
     while( line != null )
     {
      sb.append( line + "\n\r" );
      line = br.readLine();
     }
     int x = sb.indexOf("X-MSK:") ;
     if(x >-1) sMessage = sb.toString().substring(x) ;
     else sMessage = sb.toString() ;
     x = sb.indexOf("\n\r") ;
     if(x >-1) sMessage.substring(x) ;
     if(sMessage.length()>iMaxLength) return sMessage.substring(1,iMaxLength) ;
     else return sMessage ;
   }
   catch( Exception e )
   {
     e.printStackTrace();
   }
   return "" ;
  }


    // send message back to Forms
    private void SendMessage( int iNum, String sMsg ) 
    {
      try{
        CustomEvent ce = new CustomEvent(m_handler, SEND_MSG);
        if(iNum>0)
        {
          ce = new CustomEvent(m_handler, SEND_MSG);
          String sNum = "" + (iNum+1) ;
          m_handler.setProperty( MSGCOUNT, ""+iCountMsg );
          m_handler.setProperty( MSGNUM,   sNum );
          m_handler.setProperty( MSGINFO,  sMsg );
        }
        else
        { 
            ce = new CustomEvent(m_handler, SEND_ERR);
            m_handler.setProperty( MSGERROR,  sMsg );        
        }
        dispatchCustomEvent(ce);  
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }    
    }
    
    
    /*------------------------------------*
     *   Object that stores a mail entry
     *------------------------------------*/
    class MailEntry extends Object
    {
      int     iNum     = 0 ;
      String  sFrom    = "" ;
      String  sTo      = "" ;
      String  sSubject = "" ;
      String  sDate    = "" ;
      String  sMessage = "" ;
      
      MailEntry( int p_num, 
                 String p_from, 
                 String p_to, 
                 String p_subject,
                 String p_date,
                 String p_message)
      {
        iNum      = p_num ;
        sFrom     = p_from ;
        sTo       = p_to ;
        sSubject  = p_subject ;
        sDate     = p_date ;
        sMessage  = p_message ;
      }
    }  
  
}

/**
 * Builds a POP3 Header from the header returned by the Commons/Net POP3Client class
 */
class POP3Header
{
  /**
  * Maintains a map of the header keys to header values
  */
  private Map headerMap = new TreeMap();

  /**
  * Save the raw header if it is needed later
  */
  private StringBuffer rawHeader = new StringBuffer();

  /**
  * Builds a new POP3Header from a java.io.Reader, provided by the Commons/Net POP3Client class
  */
  public POP3Header( Reader r )
  {
   try
   {
     // Build a BufferedReader to read the header line-by-line
     BufferedReader br = new BufferedReader( r );
     String line = br.readLine();
     while( line != null )
     {
      // Find the index of the colon within the line
      int colonIndex = line.indexOf( ":" );
      if( colonIndex != -1 )
      {
        // The Key is the left half of the string, up to the colon
        String key = line.substring( 0, colonIndex );

        // The Value is the right half of the string, from one space
        // passed the colon to the end of the string
        String value = line.substring( colonIndex + 2 );

        // Put the key and value in the map - note that the key is lower
        // case for consistent access
        this.headerMap.put( key.toLowerCase(), value );
      }

      // Store the raw header
      this.rawHeader.append( line + "\n" );

      // Read the next line of the header
      line = br.readLine();
     }
   }
   catch( Exception e )
   {
     e.printStackTrace();
   }
  }

  /**
  * Returns the subject of the message
  */
  public String getSubject()
  {
   return getValue( "subject" );
  }

  /**
  * Returns the sender of the message
  */
  public String getFrom()
  {
   return getValue( "from" );
  }

  /**
  * Returns the recipient of the message
  */
  public String getTo()
  {
   return getValue( "to" );
  }

  /**
  * Returns the date of the message as a String
  */
  public String getDate()
  {
   return getValue( "date" );
  }

  /**
  * Returns the value that corresponds to the specified key
  */
  public String getValue( String key )
  {
   return ( String )this.headerMap.get( key );
  }

  /**
  * Debugging: return all keys and values as a string
  */
  public String toString()
  {
   StringBuffer sb = new StringBuffer( "Header Map\n" );
   for( Iterator i=this.headerMap.keySet().iterator(); i.hasNext(); )
   {
     String key = ( String )i.next();
     String value = ( String )this.headerMap.get( key );
     sb.append( "\t" + key + ": " + value + "\n" );
   }
   return sb.toString();
  }
}