package oracle.forms.fd;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
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;
import java.util.StringTokenizer;

/**
   * A Bean to handle the mouse events
   * use the Java reflexion to get the component
   * properties and methods
   * it etablish the matching between the java components
   * and the Forms module items
   *
   * @author Francois Degrelle
   * @version 1.1
   */
   
public class HandleMouseEvent2 extends VBean
{
  // variables
  private static final ID getInfos      = ID.registerProperty("GETINFOS");
  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 SET_PROP      = ID.registerProperty("SETPROP");  
  private static final ID SET_HIGLIGHT  = ID.registerProperty("SETHIGLIGHT");
  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 int          iMode = 0 ;
  private int          iInc = 20 ;
  private Color        oldColor   = null ;
  private Color        hightColor = 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 Point        point ;
  private Component[]  tComps = null ;
  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 ;
    }
    // init the item list
    else if (property == getInfos)   
    {
      getItems();
      return true ;
    }
    //SET_HIGLIGHT
     else if (property == SET_HIGLIGHT)   
     {
       String s= value.toString();
       String sItem="", sProp="" ;
       int iR, iG, iB, ipos=-1 ;
       ipos = s.indexOf(",") ;
       if(ipos>-1)
       {
         System.out.println("SETHIGHLIGHT color:"+value.toString());
         StringTokenizer st = new StringTokenizer(s,",");
         iR = Integer.parseInt(st.nextToken()) ;
         iG = Integer.parseInt(st.nextToken()) ;
         iB = Integer.parseInt(st.nextToken()) ;
         hightColor = new Color(iR,iG,iB) ;
         iMode = 1 ;
       }
       else
       {
         System.out.println("SETHIGHLIGHT:"+value.toString());
         if(s.indexOf("-")>-1) iInc = Integer.parseInt(s.substring(1)) * -1 ;
         else iInc = Integer.parseInt(s.substring(1)) ;
         iMode = 0 ;
       }
       return true ;
     }    
    // enable/disable event capture
    else if (property == SET_PROP)   
    {
      String s= value.toString();
      String sItem="", sProp="" ;
      int iPosX=0, iPosY=0 ;
      StringTokenizer st = new StringTokenizer(s,",");
      sProp = st.nextToken() ;
      iPosX = Integer.parseInt(st.nextToken()) ; 
      iPosY = Integer.parseInt(st.nextToken()) ; 
      point = new Point(iPosX, iPosY) ;
      System.out.println("SetProp "+sProp+" "+iPosX+" "+iPosY) ;
      for(int i=0; i<tComps.length; i++)
      {
         if(tComps[i].getLocation().getX() == iPosX &&
            tComps[i].getLocation().getY() == iPosY) 
         {
           tComps[i].setName(sProp);
           System.out.println("--> found "+tComps[i].getName()) ;
           return true ;
         }
      }
      return true ;
    }
    else
    {
     return super.setProperty(property, value);
    }
  }  

  /************************
   *  Get the properties  *
   ***********************/
   public Object getProperty(ID pId)
   {
     return super.getProperty(pId);
   } 

  /*
   * Etablish the correspondance between the Java component
   * and the Forms module item
   * 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 ;
    Component cpp = null ;
    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 ;
    sItem="" ;
    if( bEnter && bExit )
    {
      if(sEvent.equalsIgnoreCase("MouseEntered")) 
      {
        oldColor = cp.getBackground() ;
        if(iMode == 0) cp.setBackground(getHighlight(cp.getBackground()));
        else cp.setBackground(hightColor);
      }
      if(sEvent.equalsIgnoreCase("MouseExited")) cp.setBackground(oldColor);
    }
    // get correspondance with the Forms items
    if( ! sClass.equalsIgnoreCase("class oracle.forms.ui.VButton"))
      cpp = (cp.getParent() != null ? cp.getParent() : cp );
    else
      cpp = cp ;
    int i = 0 ;
    while(i<tComps.length)
    {
      if(tComps[i].getLocation().getX() == cpp.getLocation().getX() &&
         tComps[i].getLocation().getY() == cpp.getLocation().getY()) 
       {
         sItem = tComps[i].getName() ;
         break ;
       }
       i++;
    }
    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");
      } 
   }
   
   /*
    * get the list of components
    */
   private void getItems()
   {
     Container cont = this.getParent();
     tComps = cont.getComponents() ;
     Point pt = null ;
     for(int i=0; i<tComps.length; i++)
     {
       // output the layer hierarchy
       pt = tComps[i].getLocation();
       System.out.println("--> "+tComps[i].getName()+" ["+tComps[i].getClass()+"]"
            + pt.getX() + ","+pt.getY()) ;
     }
   }
   private Color getHighlight(Color c)  
   {
     System.out.println("inc="+iInc);
     int r,g,b ;
     int iMax = ( iInc < 0 ? 0 : 255 ) ;
     r = c.getRed() ;
     g = c.getGreen();
     b = c.getBlue() ;

     r = (r+iInc >= iMax ? r+iInc : iMax) ;
     g = (g+iInc >= iMax ? g+iInc : iMax) ;
     b = (b+iInc >= iMax ? b+iInc : iMax) ;

     return new Color(r,g,b);
   }
   
   
}
