/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */


#ifndef NMM_X_PRODUCER_HPP
#define NMM_X_PRODUCER_HPP NMM_X_PRODUCER_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/multimedia/InputProducer.hpp"

#include "nmm/comm/messaging/EventDispatcher.hpp"
#include "nmm/comm/messaging/IEventReceiver.hpp"

#include <string>

#include <X11/Xlib.h>

// #include <unistd.h>
// #include <X11/Xutil.h>


// #include "nmm/utils/thread/Thread.hpp"
// #include "nmm/video/display/interfaces/IDisplayEvents.hpp"
// #include "XVirtualImg.hpp"



namespace NMM {
  
  class XVirtualImg;
  
  /** X event producer.
   *
   * This input producer produces NMM events from X11 events.
   */
  class XProducer
    : public InputProducer
  {
  public:
    enum { F1=0, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
	   LEFT, RIGHT, UP, DOWN, ESCAPE, RETURN, PAGEUP, PAGEDOWN,
	   HOME, END, INSERT, DELETE };
    
    /** Create a new X producer.
     */
    XProducer(XVirtualImg* xvi);
    
    /** Destructor.
     */
    ~XProducer();
    
    /**
     * This method returns whether XAutoRepeat is set to false
     * while its X-Window has focus
     */
    bool isXAutoRepeat();

    /**
     * This method sets the XAutoRepeat for
     * its X-Window.
     * If true, the keyboard autorepeat is disabled while
     * the X-Window is in focus and turned on again when
     * losing focus.
     */
    void setXAutoRepeat(const bool&);
    
    // XXX: fw: this was commented out...
//     /** Registration of X-Display Input-device.
//      */
//     void registerXDisplayNode(XDisplayNode *);
    
    /** Registration of X-Display Input-device.
     *
     * This function registers the given Display-ID to the class.
     * Events that occure in the given Display will be handled by the
     * getEvent() function
     */
    void registerDisplay( Display* );

    /** Reads a XML-configuration file.
     *
     * In the configuration file are informations how events will be
     * mapped to the corresponding event-strings
     */
    bool readConfig(std::string);
    
    /**
     * retuns pressed Key (only usefull, if no receiver is connected)
     */
    bool getKey(char&);
      
      
    /**
     * Switches between processing only Mouseclicks, which are in predefined Screenrectangles or sending all MouseEvents.
     */
    void setSendingMouseEventsDirect(bool smed);
      
    /**
     * retuns Value of boolean Variable SendingMouseEventsDirect
     */
    bool isSendingMouseEventsDirect();

    /**
     * Switches between sending KeyEvents with strings or with KeySym representing the key triggering the event.
     */
    void setUsingKeySymKeyEvents(bool ukke);
      
    /**
     * retuns Value of boolean Variable UsingKeysymKeyEvents
     */
    bool isUsingKeySymKeyEvents();
    
    /**
     * Connect to event dispatcher.
     * Creates an internal event receiver with this dispatcher and connects to it.
     * Temporary, becomes obsolete as soon as EventDispatcher implements IEventReceiver.
     */
    void connectTo(EventDispatcher* dispatcher);

  private:
    /** Number of key symbols and size of event mapping table. */
    static const int KEY_NUM = 0x10000;
    
    /** Internal event receiver.
     *
     * An event receiver which forwards events to an external event
     * dispatcher.  Temporary, becomes obsolete as soon as
     * EventDispatcher implements IEventReceiver.
     */
    class InternalReceiver
      : public IEventReceiver
    {
    private:
      EventDispatcher* dispatcher;
      
    public:
      InternalReceiver();
      
      void connectTo(EventDispatcher* dispatcher);
      
      Result receiveEvent(Event&, const IEventSender* = 0);
    };
    
    struct button_coordinate_type {
      int x1;
      int y1;
      int x2;
      int y2;
      char *event;
    };
    
    typedef struct button_coordinate_type button_coordinate;
    
    Display                   *display_id;	  // X-Display ID
    
    char                      *keyevent[KEY_NUM]; // (Mapping table) Keymapping to event-strings
    vector<button_coordinate> bc;                 // (Mapping table) for button coordinates
    
    bool                      x_auto_repeat;      // XAutoRepeat (keyboard repeat)
    
    bool SendingMouseEventsDirect; //instead of checking them against given Rectangles in mmbox e.g.
    bool UsingKeySymKeyEvents;        //instead of Events with strings
    
    XVirtualImg*              xvirtualimg;
    
    InternalReceiver          internal_receiver;
    
    /**
     * The event-handling function
     * Events can be received by all registered input-devices
     * (like X-Display, Console, mouse, ...)
     */
    void handleInput();
    
    /**
     * Delete all Key-Mappings
     */
    void delete_keyevents();

    /**
     * Add key with code k and corresponding event to mapping table
     */
    bool add_key( int k, std::string event);

    /**
     * Delete all mouse coordinates-Mappings
     */
    void delete_mousecoordinates();

    /**
     * Add mouse coordinates and corresponding event to mapping table
     */
    bool add_mousecoordinates( int x1, int y1, int x2, int y2, std::string event);

    /**
     * Returns event, if given point is within a rectangle in mapping table
     */
    char *checkcoordinate( int x, int y );
    
  };

}

#include "nmm/nmm_suffix.hpp"

#endif
