package gnu.awt.xlib;

/* Copyright (C) 2000  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

import java.awt.*;

import gnu.awt.LightweightRedirector;
import gnu.gcj.xlib.Display;
import gnu.gcj.xlib.XAnyEvent;
import gnu.gcj.xlib.XExposeEvent;
import gnu.gcj.xlib.XButtonEvent;
import gnu.gcj.xlib.XConfigureEvent;
import java.awt.event.PaintEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.Vector;

public class XEventLoop
{
  Display display;
  EventQueue queue;
  XAnyEvent anyEvent;

  LightweightRedirector lightweightRedirector = new LightweightRedirector();
    
  public XEventLoop(Display display, EventQueue queue)
  {
    this.display = display;
    this.queue = queue;
    
    anyEvent = new XAnyEvent(display);
  }

  void interrupt()
  {
    anyEvent.interrupt();
  }

  void postNextEvent(boolean block)
  {
    AWTEvent evt = getNextEvent(block);
    if (evt != null)
      queue.postEvent(evt);
  }
    
  /** get next event. Will block until events become available. */
 
  public AWTEvent getNextEvent(boolean block)
  {
    // ASSERT:
    if (isIdle())
      throw new Error("should not be idle");
    
    AWTEvent event = null;
    if (loadNextEvent(block))
      {
        event = createEvent();        
        event = lightweightRedirector.redirect(event);
      }    
    return event;
  }

  boolean loadNextEvent(boolean block)
  {
    boolean gotEvent = false;
    try
      {
	setIdle(true);
	
	/* The code below will result in an XFlush(). However,
	   while we are waiting for events after calling XFlush(),
	   new X requests issued on other threads will not
	   automatically be flushed. This can lead to a deadlock
	   since XFlush() will not be called before after the
	   processing of the next event, and new events arriving
	   might be dependent on the delivery of the X
	   requests. 
	   
	   Code that issues X requests should therefore call
	   flushIfIdle() after they're done, to ensure that the
	   requests are delivered in a timely manner.  XFlush is not
	   run if event processing is underway, since we are assured
	   that the event loop execution will return to this point,
	   where requests are flushed again, before waiting for new
	   events.

	   Alternatively, do the work on the AWT thread, since the
	   XEventQueue knows how to flush the display when it runs out
	   of events. */
	
	//display.flush(); // implicit?
	gotEvent = anyEvent.loadNext(block);
      }
    catch (RuntimeException re)
      {
	System.err.println("Exception thrown on event thread:" + re);
      }
    finally
      {
	setIdle(false);
      }
    return gotEvent;
  }
    
  /**
   * @returns an AWT event created based on the current XEvent.
   * Returns null if the current XEvent does not map to any perticular
   * AWT event.
   */
    
  AWTEvent createEvent ()
  {
    int type = anyEvent.getType ();
    // Ignore some events without further processing
    switch (type)
    {
      // ignore "no expose" events, which are generated whenever a  pixmap
      // is copied to copied to a window which is entirely unobscured
      case XAnyEvent.TYPE_NO_EXPOSE:
      case XAnyEvent.TYPE_UNMAP_NOTIFY:     // ignore for now
      case XAnyEvent.TYPE_MAP_NOTIFY:       // ignore for now
      case XAnyEvent.TYPE_REPARENT_NOTIFY:  // ignore for now
        return null;
      default:
        break;  // continue processing events not in ignore list
    }
    /* avoid attempting to get client data before client data has
       been set. */
    Object peer;
    synchronized (this)
    {
      peer = anyEvent.getWindow ().getClientData ();
    }
    
    Component source = null;
    
    // Try to identify source component
    
    if (peer instanceof XCanvasPeer)
    {
      source = ((XCanvasPeer) peer).getComponent ();
    }
    
    if (source == null)
    {
      String msg = "unable to locate source for event (" +
      anyEvent + "): peer=" + peer;
      throw new RuntimeException (msg);
    }
    
    /* if a mapping from anyEvent to AWTEvent is possible, construct a
       new AWTEvent and return it. */
    
    switch (type)
    {
      case XAnyEvent.TYPE_EXPOSE:
        return createPaintEvent (source);
      case XAnyEvent.TYPE_BUTTON_PRESS:
      case XAnyEvent.TYPE_BUTTON_RELEASE:
        return createMouseEvent (type, source);
      case XAnyEvent.TYPE_CONFIGURE_NOTIFY:
        configureNotify (peer);
        return null;
        
      default:
        String msg = "Do no know how to handle event (" + anyEvent + ")";
        throw new RuntimeException (msg);
    }
  }
  
  AWTEvent createPaintEvent(Component src)
  {
    XExposeEvent expose = new XExposeEvent(anyEvent);
    PaintEvent pe = new PaintEvent(src, PaintEvent.PAINT,
				   expose.getBounds());
    return pe;
  }
    
  AWTEvent createMouseEvent(int type, Component src)
  {    
    XButtonEvent buttonEvt = new XButtonEvent(anyEvent);
    
    int modifiers = 0; //buttonToModifierMap[buttonEvt.button];
    
    /* Warning: this makes assumptions on the contents of
       X.h... Button1 = 1, Button2 = 2, etc... */
    switch (buttonEvt.button)
      {
      case 1:
	modifiers = InputEvent.BUTTON1_DOWN_MASK;
	break;
      case 2:
	modifiers = InputEvent.BUTTON2_DOWN_MASK;
	break;
      case 3:
	modifiers = InputEvent.BUTTON2_DOWN_MASK;
	break;
      }
    
    int state = buttonEvt.state;
    
    // remap bits from state to modifiers:
    
    if ((state & XButtonEvent.MASK_SHIFT) != 0)
      modifiers |= InputEvent.SHIFT_MASK;
	
	
    if ((state & XButtonEvent.MASK_CONTROL) != 0)
      modifiers |= InputEvent.CTRL_MASK;
	
    
    /* FIXME: we need additional X code to properly map MODn states to
       input modifiers */
	
    int clickCount = 1; // FIXME... Can't get this from X.
    boolean popupTrigger = false; // FIXME: look up policy somewhere
	
    int x = buttonEvt.x;
    int y = buttonEvt.y;

    int id = (type == XAnyEvent.TYPE_BUTTON_PRESS) ?
      MouseEvent.MOUSE_PRESSED :
      MouseEvent.MOUSE_RELEASED;
	
    MouseEvent me = new MouseEvent(src,
				   id,
				   buttonEvt.time, modifiers,
				   buttonEvt.x, buttonEvt.y,
				   clickCount, popupTrigger);
    return me;
  }

  void configureNotify(Object peerObj)
  {
    XConfigureEvent configEvent = new XConfigureEvent(anyEvent);
    XFramePeer peer = (XFramePeer)  peerObj;
    
    peer.configureNotify(configEvent);
  }
    
  public void flushIfIdle()
  {
    if (isIdle())
      display.flush();
  }
  
  volatile boolean idle = false;

  final synchronized void setIdle(boolean idle)
  {
    this.idle = idle;
  }

  final synchronized boolean isIdle()
  {
    return idle;
  }
}
