package oracle.forms.fd;

import java.awt.Component;
import java.awt.Point;
import oracle.forms.handler.IHandler;
import oracle.forms.ui.FormMouseGrabProvider;
import oracle.forms.ui.VBean;
import oracle.forms.properties.ID;
import oracle.forms.ui.CustomEvent;
import oracle.forms.engine.Main;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
   * A Bean to handle the mouse events
   * use the Java reflexion to get the component
   * properties and methods
   *
   * @author Francois Degrelle
   * @version 1.0
   */
   
public class HandleMouseEvent extends VBean
{
  // variables
  private static final ID setEvent      = ID.registerProperty("SETEVENT");
  private static final ID AllowEvent    = ID.registerProperty("ALLOWEVENT");  
  private static final ID SEND_MSG      = ID.registerProperty("SENDMSG");        
  private static final ID SEND_PROPS    = ID.registerProperty("SENDPROPS");  
  private static final ID MSGPROPS      = ID.registerProperty("MSGPROPS");     
  private static final ID MSGEVENT      = ID.registerProperty("MSGEVENT");       
  private static final ID MSGCOORD      = ID.registerProperty("MSGCOORD");         
  private static final ID MSGITEM       = ID.registerProperty("MSGITEM");         
  private static final ID MSGBTMOUSE    = ID.registerProperty("MSGBTMOUSE");           
  private IHandler     m_handler;  
  private Main         formsMain = null;
  private boolean      bMove  = false ;
  private boolean      bEnter = true ;  
  private boolean      bExit  = true ;  
  private boolean      bClick = true ;  
  private boolean      bPress = true ;
  private boolean      bRel   = true ;  
  private boolean      bGetEvents = true ;
  private String       sItem = "" ;
  private String       sEvent = "" ;
  private String       sCoord = "" ;
  private String       sButton = "" ;
  private StringBuffer sbProperties = new StringBuffer() ;
  
  public void init(IHandler handler)
  {
    m_handler = handler;
    super.init(handler);
    // getting the Forms Main class
    formsMain  =  (Main) handler.getApplet();
    // add mouse listener to the Forms module
    _addMouseListeners(formsMain.getCursorGrabProvider());

  }  
  
    public void _addMouseListeners (FormMouseGrabProvider c)
    {
      c.addMouseMotionGrab(new MouseMotionListener(){

      public void mouseMoved(MouseEvent me)
      {
        if(bMove) handleComponent(me.getComponent(), me, "mouseMoved");       
      }
      public void mouseDragged(MouseEvent me)
      {
        // drag and drop is not supported in Forms9i and 10g. Therefore the
        // drag event is useless to capture
      }
    });

    c.addMouseGrab(new MouseListener(){

        public void mouseExited(MouseEvent me)
        {
          if(bExit) handleComponent(me.getComponent(), me, "mouseExited");          
        }
        public void mouseEntered(MouseEvent me)
        {
          if(bEnter) handleComponent(me.getComponent(), me, "mouseEntered");
        }
        public void mousePressed(MouseEvent me)
        {
          if(bPress) handleComponent(me.getComponent(), me, "mousePressed");          
        }
        public void mouseReleased(MouseEvent me)
        {
          if(bRel) handleComponent(me.getComponent(), me, "mouseReleased");          
        }
        public void mouseClicked(MouseEvent me)
        {
          if(bClick) handleComponent(me.getComponent(), me, "mouseClicked");          
        }
    });
  }  
  
  /*************************
   *  Set some properties  *
   ************************/
  public boolean setProperty(ID property, Object value)
  {
    /***************************
     *  enable/disable events  *
     ***************************/
    // enable/disable individual event
    if (property == setEvent)   
    {
      String s="", sEvent="", sFlag="" ;
      int    ipos=-1;
      boolean bFlag = false ;
      s = value.toString();
      ipos = s.indexOf("=") ;
      if(ipos > -1)
      {
        sEvent = s.substring(0,ipos);
        sFlag  = s.substring(ipos+1);
        if(sFlag.equalsIgnoreCase("true")) bFlag = true ;
        if(sEvent.equalsIgnoreCase("move"))  bMove = bFlag ;
        if(sEvent.equalsIgnoreCase("enter")) bEnter = bFlag ;
        if(sEvent.equalsIgnoreCase("exit"))  bExit = bFlag ;
        if(sEvent.equalsIgnoreCase("press")) bPress = bFlag ;
        if(sEvent.equalsIgnoreCase("click")) bClick = bFlag ;
      }
      return true ;
    }
    // enable/disable event capture
    else if (property == AllowEvent)   
    {
      String s= value.toString();
      if(s.equalsIgnoreCase("true")) bGetEvents = true ;
      else bGetEvents = false ;
    return true ;
  }
    else
    {
     return super.setProperty(property, value);
    }
  }  

  /************************
   *  Get the properties  *
   ***********************/
   public Object getProperty(ID pId)
   {
     return super.getProperty(pId);
   } 

  /*
   * display information about the mouse state, location
   * and the component that raised the event
   */
  private void handleComponent(Component cp, MouseEvent me, String sEventName)
  {
    if(!bGetEvents) return ;
    String sClass = cp.getClass().toString();
    Point  pt = me.getPoint() ;
    double iX = pt.getX() ;
    double iY = pt.getY() ;
    sCoord = ""+iX+","+iY ;
    sButton = "" + me.getButton() ;
    sEvent = sEventName ;
    // tree
    if(sClass.indexOf("oracle.ewt.dTree.DTree") >-1)
    {
      sItem = "Tree" ;
    }
    //poplist
    else if(sClass.indexOf("oracle.forms.ui.VPopList") >-1)
    {
      sItem="PopList" ;
    }    
    // Tlist
    else if(sClass.indexOf("oracle.ewt.lwAWT.LWDataSourceList") >-1)
    {
      sItem="TList" ;
    }        
    // Combo list
    else if(sClass.indexOf("oracle.ewt.comboBox.ComboBox") >-1)
    {
      sItem="ComboList" ;
    }        
    // text item
    else if(sClass.indexOf("oracle.forms.ui.VTextField") >-1)
    {
      sItem="TextField" ;
    }    
    // text area
    else if(sClass.indexOf("oracle.forms.ui.VTextArea") >-1 ||
            sClass.indexOf("oracle.ewt.lwAWT.lwText.LWTextArea") >-1)
    {
      sItem="TextArea" ;
    }    
    // Bean area  
     else if(sClass.indexOf("oracle.forms.ui.VBean") >-1)
     {
       sItem="Bean" ;
     }        
    // image  
     else if(sClass.indexOf("oracle.ewt.imageCanvas.ScalingImageCanvas") >-1 ||
             sClass.indexOf("oracle.forms.ui.VImage") >-1)
      {
        sItem="Image" ;
      }        
    // radio group
    else if(sClass.indexOf("oracle.forms.ui.VRadioButton") >-1)
     {
       sItem="Radio Group" ;
     }        
    // radio button
    else if(sClass.indexOf("oracle.forms.ui.ExtendedCheckbox") >-1)
    {
      sItem="Radio Button" ;
    }    
    // check box frame
    else if(sClass.indexOf("oracle.ewt.lwAWT.LWCheckbox") >-1)
    {
      sItem="Check Box frame" ;
    }    
    // check box
    else if( sClass.indexOf("oracle.forms.ui.VCheckbox") >-1 )
    {
      sItem="Check Box" ;
    }        
    // push button
    else if(sClass.indexOf("oracle.forms.ui.VButton") >-1)
    {
      sItem="Push Button" ;
    }    
    // canvas
    else if(sClass.indexOf("oracle.forms.ui.DrawnPane") >-1)
    {
      sItem="Canvas" ;
    }    
    // Tab canvas 
     else if(sClass.indexOf("oracle.ewt.tabPanel.TabPanelSheet") >-1)
     {
       sItem="Tab Canvas" ;
     }        
    // Tab page 
     else if(sClass.indexOf("oracle.ewt.tabBar.TabBar") >-1)
     {
       sItem="Tab Page" ;
     }             
    // status bar
    else if(sClass.indexOf("oracle.forms.ui.FormStatusArea") >-1 &&
            sClass.indexOf("oracle.ewt.statusBar.StatusBar") >-1)
    {
      sItem="Status bar" ;
    }    
    else
      {
         sItem=sClass;      
         System.out.println(sClass);
      }
      
    // send the event message to Forms
    SendMessage() ;  
    // if right-click, send properties message to Forms
    if(sButton.endsWith("3"))
    {
      bGetEvents = false ;
      // get the component properties
      exploreField(cp);
      // get the component methods
      exploreMethods(cp);
      // send all to Forms
      SendProperties();
      bGetEvents = true ;
    }
  }

  // send message back to Forms
  private void SendMessage() 
  {
    try{
      CustomEvent ce = new CustomEvent(m_handler, SEND_MSG);
      m_handler.setProperty( MSGITEM, sItem );
      m_handler.setProperty( MSGEVENT, sEvent );
      m_handler.setProperty( MSGCOORD, sCoord );
      m_handler.setProperty( MSGBTMOUSE, sButton );
      dispatchCustomEvent(ce);  
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }    
  }

  // send component properties back to Forms
  private void SendProperties() 
  {
    try{
      CustomEvent ce = new CustomEvent(m_handler, SEND_PROPS);
      m_handler.setProperty( MSGPROPS, sbProperties.toString() );
      dispatchCustomEvent(ce);  
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }    
  }

  /*
   *   Reflexion methods
   */
  public void exploreField(Object o)
   {
      Field[] f = null;
      Class c = null;
    
      c = o.getClass();
      f = c.getFields();
      consultField(f,o);
   }
  
   public void exploreMethods(Object o)
   {
      Method[] m = null;
      Class c = null;
    
      c = o.getClass();
      m= c.getMethods();
      consultMethods(m);
   }
  
   private void consultField(Field[] f, Object o)
   {
      sbProperties = new StringBuffer("  ** component properties **/n") ;
      for(int i=0;i<f.length;++i)
      {      
         sbProperties.append(Modifier.toString(f[i].getModifiers())) ;
         sbProperties.append(" ");
         sbProperties.append(f[i].getType().getName());
         sbProperties.append(" ");
         sbProperties.append(f[i].getName());
         sbProperties.append(" = ");
         try
         {
            sbProperties.append(f[i].get(o)+"/n");
         }
         catch (IllegalAccessException e)
         {
           sbProperties.append("Unable to get value/n");
         }
      }
   }
  
   private void consultMethods(Method[] m)
   {
      Class[] params = null;
     sbProperties.append("/n  ** component methods **/n");
      for(int i=0;i<m.length;++i) 
      {      
         sbProperties.append(Modifier.toString(m[i].getModifiers()));
         sbProperties.append(" ");
         sbProperties.append(m[i].getReturnType().getName());
         sbProperties.append(" ");
         sbProperties.append(m[i].getName());
         sbProperties.append("(");
         params = m[i].getParameterTypes();
         for(int j=0;j<params.length;++j)
         {
           sbProperties.append(params[j].getName());
         }
         sbProperties.append(")/n");
      } 
   }
  
}
