/* QtComponentPeer.java --
   Copyright (C)  2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.java.awt.peer.qt;

import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Component;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.image.ColorModel;
import java.awt.image.VolatileImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.event.ComponentEvent; // 100%
import java.awt.event.FocusEvent; // 100%
import java.awt.event.InputEvent; // (abstract)
import java.awt.event.KeyEvent; // 2/3
import java.awt.event.MouseEvent; // 70%? 
import java.awt.event.PaintEvent; // Yup.
import java.awt.event.WindowEvent; // 2/ 12
import java.util.Timer;
import java.util.TimerTask;

public class QtComponentPeer extends NativeWrapper implements ComponentPeer
{

  /**
   * Popup trigger button, may differ between platforms
   */
  protected static final int POPUP_TRIGGER = 3;

  /**
   * The toolkit which manufactured this peer.
   */
  protected QtToolkit toolkit;

  /**
   * The component which owns this peer.
   */
  Component owner;

  /**
   * Classpath updates our eventMask.
   */
  private long eventMask;

  /**
   * if the thing has mouse motion listeners or not.
   */
  private boolean hasMotionListeners;

  /**
   * The component's double buffer for off-screen drawing.
   */
  protected QtImage backBuffer;

  protected long qtApp;

  private boolean settingUp;

  private boolean ignoreResize = false;

  QtComponentPeer( QtToolkit kit, Component owner )
  {
    this.owner = owner;
    this.toolkit = kit;
    qtApp = QtToolkit.guiThread.QApplicationPointer;
    nativeObject = 0;
    synchronized(this) 
      {
	callInit(); // Calls the init method FROM THE MAIN THREAD.
	try
	  {	
	    wait(); // Wait for the thing to be created.
	  }
	catch(InterruptedException e)
	  {
	  }
      }
    setup();
    hasMotionListeners = false;
  }

  protected native void callInit();

  /**
   * Init does the creation of native widgets, it is therefore
   * called from the main thread. (the constructor waits for this to happen.)
   */
  protected void init()
  {
  }

  protected void setup()
  {
    settingUp = true;
    if (owner != null)
      {
  	if (owner instanceof javax.swing.JComponent)
  	  setBackground(owner.getBackground());
  	else
	  owner.setBackground(getNativeBackground());
	
	if (owner.getForeground() != null)
	  setForeground(owner.getForeground());
	else
	  setForeground( Color.black );

	if (owner.getCursor() != null)
	  if (owner.getCursor().getType() != Cursor.DEFAULT_CURSOR)
	    setCursor(owner.getCursor());
	
	if (owner.getFont() != null)
	  setFont(owner.getFont());

	setEnabled( owner.isEnabled() );

	backBuffer = null;
	updateBounds();

	setVisible( owner.isVisible() );
	QtToolkit.repaintThread.queueComponent(this);
      }
    settingUp = false;
  }

  native void QtUpdate();
  native void QtUpdateArea( int x, int y, int w, int h );
  private synchronized native void disposeNative();
  private native void setGround( int r, int g, int b, boolean isForeground );
  private native void setBoundsNative( int x, int y, int width, int height );
  private native void setCursor( int ctype );
  private native Color getNativeBackground();
  private native void setFontNative( QtFontPeer fp );
  private native int whichScreen();
  private native void reparentNative( QtContainerPeer parent );
  private native void getLocationOnScreenNative( Point p );

  private boolean drawableComponent()
  {
    return ((this instanceof QtContainerPeer && 
	     !(this instanceof QtScrollPanePeer)) || 
	    (this instanceof QtCanvasPeer));
  }

  void updateBounds()
  {
    Rectangle r = owner.getBounds();
    setBounds( r.x, r.y, r.width, r.height );
  }

  synchronized void updateBackBuffer(int width, int height)
  {
    if(width <= 0 || height <= 0)
      return;
    
    if( !drawableComponent() && backBuffer == null)
      return;

    if( backBuffer != null )
      {
	if( width < backBuffer.width && height < backBuffer.height )
	  return;
	backBuffer.dispose();
      }
    backBuffer = new QtImage(width, height);
  }
	

  // ************ Event methods *********************

  /**
   * Window closing event
   */
  protected void closeEvent()
  {
    if (owner instanceof Window)
      {
	WindowEvent e = new WindowEvent((Window)owner, 
					WindowEvent.WINDOW_CLOSING);
	QtToolkit.eventQueue.postEvent(e);
      }
  }

  protected void enterEvent(int modifiers, int x, int y, int dummy)
  {
    MouseEvent e = new MouseEvent(owner, 
				  MouseEvent.MOUSE_ENTERED,
				  System.currentTimeMillis(),
				  (modifiers & 0x2FF), x, y, 0, false);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void focusInEvent()
  {
    FocusEvent e = new FocusEvent(owner, FocusEvent.FOCUS_GAINED);
    QtToolkit.eventQueue.postEvent(e);
   }

  protected void focusOutEvent()
  {
    FocusEvent e = new FocusEvent(owner, FocusEvent.FOCUS_LOST);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void keyPressEvent(int modifiers, int code, int unicode, int dummy)
  {
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
    KeyEvent e = new KeyEvent(owner, 
			      KeyEvent.KEY_PRESSED,
			      System.currentTimeMillis(),
			      modifiers, code, (char)(unicode & 0xFFFF),
			      KeyEvent.KEY_LOCATION_UNKNOWN);
    if (!manager.dispatchEvent (e))
      QtToolkit.eventQueue.postEvent(e);
  }

  protected void keyReleaseEvent(int modifiers, int code, int unicode, int dummy)
  {
    KeyEvent e = new KeyEvent(owner, 
			      KeyEvent.KEY_RELEASED,
			      System.currentTimeMillis(),
			      modifiers, code, (char)(unicode & 0xFFFF),
			      KeyEvent.KEY_LOCATION_UNKNOWN);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void leaveEvent(int modifiers, int x, int y, int dummy)
  {
    MouseEvent e = new MouseEvent(owner, 
				  MouseEvent.MOUSE_EXITED,
				  System.currentTimeMillis(),
				  (modifiers & 0x2FF), x, y, 0, false);
    QtToolkit.eventQueue.postEvent(e);
  }

  // FIXME: Coalesce press-release events into clicks.
  protected void mouseDoubleClickEvent( int modifiers, int x, int y, int clickCount)
  {
    if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
      return;
    int button = 0;
    if((modifiers & InputEvent.BUTTON1_DOWN_MASK) == 
       InputEvent.BUTTON1_DOWN_MASK) button = 1;
    if((modifiers & InputEvent.BUTTON2_DOWN_MASK) == 
       InputEvent.BUTTON2_DOWN_MASK) button = 2;
    if((modifiers & InputEvent.BUTTON3_DOWN_MASK) == 
       InputEvent.BUTTON3_DOWN_MASK) button = 3;
    MouseEvent e = new MouseEvent(owner, 
				  MouseEvent.MOUSE_CLICKED,
				  System.currentTimeMillis(),
				  (modifiers & 0x2FF), x, y, clickCount, 
				  false, button);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void mouseMoveEvent( int modifiers, int x, int y, int clickCount)
  {
    if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
      return;

    int button = 0;
    if((modifiers & InputEvent.BUTTON1_DOWN_MASK) == 
       InputEvent.BUTTON1_DOWN_MASK) button = 1;
    if((modifiers & InputEvent.BUTTON2_DOWN_MASK) == 
       InputEvent.BUTTON2_DOWN_MASK) button = 2;
    if((modifiers & InputEvent.BUTTON3_DOWN_MASK) == 
	   InputEvent.BUTTON3_DOWN_MASK) button = 3;

    int type = (button != 0) ? 
      MouseEvent.MOUSE_DRAGGED :MouseEvent.MOUSE_MOVED;
    
    MouseEvent e = new MouseEvent(owner, 
				  type,
				  System.currentTimeMillis(),
				  (modifiers & 0x2FF), x, y, clickCount, 
				  false, button);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void mousePressEvent( int modifiers, int x, int y, int clickCount)
  {
    if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
      return;
    int button = 0;
    if((modifiers & InputEvent.BUTTON1_DOWN_MASK) == 
       InputEvent.BUTTON1_DOWN_MASK) button = 1;
    if((modifiers & InputEvent.BUTTON2_DOWN_MASK) == 
       InputEvent.BUTTON2_DOWN_MASK) button = 2;
    if((modifiers & InputEvent.BUTTON3_DOWN_MASK) == 
       InputEvent.BUTTON3_DOWN_MASK) button = 3;
    MouseEvent e = new MouseEvent(owner, 
				  MouseEvent.MOUSE_PRESSED,
				  System.currentTimeMillis(),
				  (modifiers & 0x2FF), x, y, clickCount, 
				  ( button == POPUP_TRIGGER ), 
				   button);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void mouseReleaseEvent( int modifiers, int x, int y, int clickCount)
  {
    if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
      return;
    int button = 0;
    if((modifiers & InputEvent.BUTTON1_DOWN_MASK) == 
       InputEvent.BUTTON1_DOWN_MASK) button = 1;
    if((modifiers & InputEvent.BUTTON2_DOWN_MASK) == 
       InputEvent.BUTTON2_DOWN_MASK) button = 2;
    if((modifiers & InputEvent.BUTTON3_DOWN_MASK) == 
       InputEvent.BUTTON3_DOWN_MASK) button = 3;

    MouseEvent e = new MouseEvent(owner, 
				  MouseEvent.MOUSE_RELEASED,
				  System.currentTimeMillis(),
				  (modifiers & 0x2FF), x, y, clickCount, 
				  false, button);
    QtToolkit.eventQueue.postEvent(e);
  }

  protected void moveEvent(int x, int y, int oldx, int oldy)
  {
    if( !ignoreResize )
      {
	// Since Component.setLocation calls back to setBounds, 
	// we need to ignore that.
	ignoreResize = true; 
	owner.setLocation( x, y );
	ignoreResize = false;
      }
  }

  protected void resizeEvent(int oldWidth, int oldHeight, 
			     int width, int height)
  {
    if(!(owner instanceof Window))
      return;
    updateBackBuffer(width, height);
    ignoreResize = true;
    owner.setSize(width, height);
    ignoreResize = false;
    ComponentEvent e = new ComponentEvent(owner, 
  					  ComponentEvent.COMPONENT_RESIZED);
    QtToolkit.eventQueue.postEvent(e);
    QtToolkit.repaintThread.queueComponent(this);
  }

  protected void showEvent()
  {
    if (owner instanceof Window)
      {
	WindowEvent e = new WindowEvent((Window)owner, 
					WindowEvent.WINDOW_OPENED);
	QtToolkit.eventQueue.postEvent(e);
      }
    else 
      {
	ComponentEvent e = new ComponentEvent(owner, 
					      ComponentEvent.COMPONENT_SHOWN);
	QtToolkit.eventQueue.postEvent(e);
      }
  }

  protected void hideEvent()
  {
    ComponentEvent e = new ComponentEvent(owner, 
					  ComponentEvent.COMPONENT_HIDDEN);
    QtToolkit.eventQueue.postEvent(e);
  }

  // ************ Public methods *********************

  /** Classpath-specific method */
  public void setEventMask(long x)
  {
    eventMask = x;
  }


  public boolean canDetermineObscurity()
  {
    return true;
  } 

  public int checkImage(Image img,
			int w,
			int h,
			ImageObserver o)
  {
    return toolkit.checkImage(img, w, h, o);
  }

  public void createBuffers(int numBuffers, BufferCapabilities caps)
    throws AWTException 
  {
    // FIXME
  }

  public Image createImage(ImageProducer producer)
  {
    return toolkit.createImage(producer);
  }

  public Image createImage(int width, int height)
  {
    return new QtImage(width, height);
  }

  public void coalescePaintEvent(PaintEvent e)
  {
    // FIXME
  }

  public VolatileImage createVolatileImage(int w, int h)
  {
    return new QtVolatileImage( w, h );
  }

  public void destroyBuffers()
  {
    // FIXME
  }

  public void disable()
  {
    setEnabled(false);
  }

  public void dispose()
  {
    disposeNative();
    if( backBuffer != null )
      backBuffer.dispose();
  }

  public void enable()
  {
    setEnabled(true);
  }

  public void finalize()
  {
    dispose();
  }

  public void flip(BufferCapabilities.FlipContents contents)
  {
  }

  public Image getBackBuffer()
  {
    return backBuffer;
  }

  public ColorModel getColorModel()
  {
    return toolkit.getColorModel();
  }

  public FontMetrics getFontMetrics(Font font)
  {
    return new QtFontMetrics( font, getGraphics() );
  }

  public Graphics getGraphics()
  {
    if( backBuffer == null )
      { 
	Rectangle r = owner.getBounds();
	backBuffer = new QtImage( r.width, r.height );
      }
    return backBuffer.getDirectGraphics( this );
  }

  public GraphicsConfiguration getGraphicsConfiguration()
  {
    int id = whichScreen(); // get the ID of the screen the widget is on.
    GraphicsDevice[] devs = QtToolkit.graphicsEnv.getScreenDevices();
    return devs[id].getDefaultConfiguration();
  }

  public Point getLocationOnScreen()
  {
    Point p = new Point();
    synchronized( p ) 
      {
	getLocationOnScreenNative( p );
	try
	  {	
	    p.wait(); // Wait for the thing to be created.
	  }
	catch(InterruptedException e)
	  {
	  }
      }
    return p;
  }

  private native void getSizeNative(Dimension d, boolean preferred);

  private Dimension getSize(boolean preferred)
  {
    Dimension d = new Dimension();
    synchronized( d ) 
      {
	getSizeNative(d, preferred);
	try
	  {	
	    d.wait(); // Wait for the thing to be created.
	  }
	catch(InterruptedException e)
	  {
	  }
      }
    return d;
  }

  public Dimension getMinimumSize()
  {
    return getSize( false );
  }
 
  public Dimension getPreferredSize()
  {
    return getSize( true );
  }

  public Toolkit getToolkit()
  {
    return toolkit;
  }

  public native boolean handlesWheelScrolling();
   
  public void hide()
  {
    setVisible(false);
  }

  public native boolean isFocusable();

  public boolean isFocusTraversable()
  {
    // FIXME
    return false;
  }

  public native boolean isObscured();

  public Dimension minimumSize()
  {
    return getMinimumSize();
  }

  public Dimension preferredSize()
  {
    return getPreferredSize();
  }

  public native void requestFocus();

  public boolean requestFocus (Component source, boolean bool1, 
			       boolean bool2, long x)
  {
    // FIXME
    return true;
  }

  public void reshape(int x,
		      int y,
		      int width,
		      int height)
  {
    setBounds( x, y, width, height );
  }

  public void setBackground(Color c)
  {
    if(c == null && !settingUp)
      return;
    setGround(c.getRed(), c.getGreen(), c.getBlue(), false);
  }

  public void setBounds(int x, int y, int width, int height)
  {
    if( ignoreResize )
      return;
    updateBackBuffer(width, height);
    QtToolkit.repaintThread.queueComponent(this);
    setBoundsNative(x, y, width, height);
  }

  public void setCursor(Cursor cursor)
  {
    if (cursor != null)
      setCursor(cursor.getType());
  }

  public native void setEnabled(boolean b);

  public void setFont(Font f)
  {
    if( f == null || f.getPeer() == null)
      throw new IllegalArgumentException("Null font.");
    setFontNative( (QtFontPeer)f.getPeer() );
  }

  public void setForeground(Color c)
  {
    if(c == null && !settingUp)
      return;
    setGround(c.getRed(), c.getGreen(), c.getBlue(), true);
  }
  
  public native void setVisible(boolean b);

  public void show()
  {
    setVisible(true);
  }

  public void handleEvent (AWTEvent e)
  {
    int eventID = e.getID();
    Rectangle r;

    switch (eventID)
      {
      case ComponentEvent.COMPONENT_SHOWN:
	QtToolkit.repaintThread.queueComponent(this);
        break;
      case PaintEvent.PAINT:
      case PaintEvent.UPDATE:	
	r = ((PaintEvent)e).getUpdateRect();
	QtToolkit.repaintThread.queueComponent(this, r.x, r.y,
					       r.width, r.height);
        break;
      case KeyEvent.KEY_PRESSED:
	break;
      case KeyEvent.KEY_RELEASED:
	break;
      }
  }

  /**
   * paint() is called back from the native side in response to a native
   * repaint event.
   */  
  public void paint(Graphics g)
  {
    Rectangle r = g.getClipBounds();

    if (backBuffer != null)
      backBuffer.drawPixelsScaledFlipped ((QtGraphics) g, 
					  0, 0, 0, /* bg colors */
					  false, false, /* no flipping */
					  r.x, r.y, r.width, r.height,
					  r.x, r.y, r.width, r.height,
					  false ); /* no compositing */
  }

  public void paintBackBuffer() throws InterruptedException
  {
    if( backBuffer != null )
      {
	backBuffer.clear();
	Graphics2D bbg = (Graphics2D)backBuffer.getGraphics();
	owner.paint(bbg); 
	bbg.dispose();
      }
  }

  public void paintBackBuffer(int x, int y, int w, int h) 
    throws InterruptedException
  {
    if( backBuffer != null )
      {
	Graphics2D bbg = (Graphics2D)backBuffer.getGraphics();
	bbg.setBackground( getNativeBackground() );
	bbg.clearRect(x, y, w, h);
	bbg.setClip(x, y, w, h);
	owner.paint(bbg); 
	bbg.dispose();
      }
  }

  public boolean prepareImage(Image img,
			      int w,
			      int h,
			      ImageObserver o)
  {
    return toolkit.prepareImage(img, w, h, o);
  }
  
  public void print(Graphics g)
  {
    // FIXME
  }

  /**
   * Schedules a timed repaint.
   */
  public void repaint(long tm,
		      int x,
		      int y,
		      int w,
		      int h)
  {
    if( tm <= 0 )
      {
	QtToolkit.repaintThread.queueComponent(this, x, y, w, h);
	return;
      }      
    Timer t = new Timer();
    t.schedule(new RepaintTimerTask(this, x, y, w, h), tm);
  }

  /**
   * Update the cursor (note that setCursor is usually not called)
   */
  public void updateCursorImmediately()
  {
    if (owner.getCursor() != null)
      setCursor(owner.getCursor().getType());
  }

  /**
   * Timed repainter
   */
  private class RepaintTimerTask extends TimerTask 
  {    
    private int x, y, w, h;
    private QtComponentPeer peer;
    RepaintTimerTask(QtComponentPeer peer, int x, int y, int w, int h)
    { 
      this.x=x;
      this.y=y;
      this.w=w;
      this.h=h; 
      this.peer=peer;
    }
    public void run()
    { 
      QtToolkit.repaintThread.queueComponent(peer, x, y, w, h);
    }
  }

  public native Rectangle getBounds();

  public void reparent(ContainerPeer parent)
  {
    if(!(parent instanceof QtContainerPeer))
      throw new IllegalArgumentException("Illegal peer.");
    reparentNative((QtContainerPeer)parent);
  }

  public void setBounds(int x, int y, int width, int height, int z)
  {
    // TODO Auto-generated method stub
    
  }

  public boolean isReparentSupported()
  {
    return true;
  }

  // What does this do, anyway?
  public void layout()
  {
    // TODO Auto-generated method stub
  }
}
