/* XGraphicsDevice.java -- GraphicsDevice for X
   Copyright (C) 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.x;

import gnu.classpath.SystemProperties;
import gnu.x11.Display;
import gnu.x11.EscherServerConnectionException;

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.lang.reflect.Constructor;
import java.net.Socket;

/**
 * This class represents an X Display. The actual connection is established
 * lazily when it is first needed.
 *
 * @author Roman Kennke (kennke@aicas.com)
 */
public class XGraphicsDevice
  extends GraphicsDevice
{

  private XGraphicsConfiguration defaultConfiguration;

  /**
   * The X display associated with the XGraphicsDevice. This is established
   * when {@link #getDisplay} is first called.
   */
  private Display display;

  /**
   * The display name from which the display will be initialized.
   */
  private Display.Name displayName;

  /**
   * The event pump for this X Display.
   */
  private XEventPump eventPump;

  /**
   * Creates a new XGraphicsDevice.
   */
  XGraphicsDevice(Display.Name dn)
  {
    displayName = dn;
  }

  public int getType()
  {
    return TYPE_RASTER_SCREEN;
  }

  public String getIDstring()
  {
    // TODO: Implement this.
    throw new UnsupportedOperationException("Not yet implemented.");
  }

  public GraphicsConfiguration[] getConfigurations()
  {
    // TODO: Implement this.
    throw new UnsupportedOperationException("Not yet implemented.");
  }

  public GraphicsConfiguration getDefaultConfiguration()
  {
    if (defaultConfiguration == null)
      defaultConfiguration = new XGraphicsConfiguration(this);
    return defaultConfiguration;
  }

  /**
   * Returns the X Display associated with this XGraphicsDevice.
   * This establishes the connection to the X server on the first invocation.
   *
   * @return the X Display associated with this XGraphicsDevice
   */
  Display getDisplay()
  {
    if (display == null)
      {
        if (displayName.hostname.equals(""))
          displayName.hostname = "localhost";
        if (XToolkit.DEBUG)
          System.err.println("connecting to : " + displayName);
        // Try to connect via unix domain sockets when host == localhost.
        if ((displayName.hostname.equals("localhost")
             || displayName.hostname.equals(""))
          && SystemProperties.getProperty("gnu.xawt.no_local_sockets") == null)
          {
            Socket socket = createLocalSocket();
            if (socket != null)
              {
                try
                  {
                    display = new Display(socket, "localhost",
                                          displayName.display_no,
                                          displayName.screen_no);
                  }
                catch (EscherServerConnectionException e)
                  {
                    throw new RuntimeException(e.getCause()); 
                  }
              }
          }

        // The following happens when we are configured to use plain sockets,
        // when the connection is probably remote or when we couldn't load
        // the LocalSocket class stuff.
        if (display == null)
          {
            try
              {
                display = new Display(displayName);
              }
            catch (EscherServerConnectionException e)
              {
                throw new RuntimeException(e.getCause());
              }
          }
        
        eventPump = new XEventPump(display);
      }
    return display;
  }

  XEventPump getEventPump()
  {
    return eventPump;
  }

  /**
   * Tries to load the LocalSocket class and initiate a connection to the 
   * local X server.
   */
  private Socket createLocalSocket()
  {
    Socket socket = null;
    try
      {
        // TODO: Is this 100% ok?
        String sockPath = "/tmp/.X11-unix/X" + displayName.display_no;
        Class localSocketAddressClass =
          Class.forName("gnu.java.net.local.LocalSocketAddress");
        Constructor localSocketAddressConstr =
          localSocketAddressClass.getConstructor(new Class[]{ String.class });
        Object addr =
          localSocketAddressConstr.newInstance(new Object[]{ sockPath });
        Class localSocketClass =
          Class.forName("gnu.java.net.local.LocalSocket");
        Constructor localSocketConstructor =
          localSocketClass.getConstructor(new Class[]{localSocketAddressClass});
        Object localSocket =
          localSocketConstructor.newInstance(new Object[]{ addr });
        socket = (Socket) localSocket;
      }
    catch (Exception ex)
      {
        // Whatever goes wrong here, we return null.
      }
    return socket;
  }
}
