#ifndef __STK_MESSAGE
#define __STK_MESSAGE

/* This is the fourth rewrittring of messages:
   For each application, we create  a Looper. Each looper contains a
   list of progs. And each programs contains a list of Handler sons.
   So we can build a hiearchy.
*/


#include "stk_thread.h"

#include <list>
#include <string>
using namespace std;



class Stk_Looper;
class Stk_Prog;
class Stk_PassiveSender;


/* ------------------------ Messages --------------------------- */

// list of unique type for messages
#define   STK_KEY_EVENT       100
#define   STK_JOY_EVENT       101
#define   STK_MOU_EVENT       102

/*
  KEYBOARD EVENT:                                                       \\
  message one about ascii keys with fields:                             \\
  - type: 1                                                             \\
  - key: an int values containing the char value                        \\
  - pressed: int flag indicate state                                    \\
  message two about special keys (listed in stk_keyboard.h:)            \\
  - type: 2                                                             \\
  - key: an int value describing the key                                \\
  - pressed: an int indicate its state                                  \\
  

  MOUSE EVENT:                                                          \\
  message one about button press with fields:                           \\
  - type: 1                                                             \\
  - button: number of button (1: LEFT 2:MIDDLE 3:RIGHT)                 \\
  - pressed: an int indicate its state                                  \\
  - x,y: position (int) of cursor                                       \\
  message two about pointer move:                                       \\
  - type: 2                                                             \\
  - x,y: position (int) of cursor                                       \\
 */



/** this class is a field for a message. A field is composed with: \\
 - a name                                                          \\
 - a value (all type are possible)                                 \\
*/
class Stk_Field
{
    friend class Stk_Message;
public:
        /// construct a field for a message
    Stk_Field(const char *);
        /// copy constructor
    Stk_Field(const Stk_Field &);
        /// destructor
    ~Stk_Field();
        /// operator =
    const Stk_Field &operator=(const Stk_Field &);
private:
    string name;
    void *value;
};





/** This class represents a message. It allows
 easy communication between keyboard, joy and
 progs. */
class Stk_Message
{
public:
        /// null constructor
    Stk_Message();
        /// constructor with type
    Stk_Message(int type);
    
        /// destructor
    virtual ~Stk_Message();
    

        /** The type determines how to manage it.
            you must have an unique id for each class
            message */
    int what;

        // functions
        /// Add a field named name containing an Int value
    int AddInt(const char *name,int anInt);
        /// Add a field named name containing an float value
    int AddFloat(const char *name,float aFloat);
    
        /// find a field containing an Int value
    int FindInt(const char *name,int *&);
        /// find a field containing an Float value
    int FindFloat(const char *name,float *&);

private:
    list<Stk_Field *> fields;
};







/* ------------ template type for queue ------------------- */
/** A template type for synchrone queue. Elements will be deleted
    when there are removed from list !
 */
template <class T>
class Stk_Queue
{
public:
        /// Constructor
    Stk_Queue();
        /// Destructor
    virtual ~Stk_Queue();
        /// Synchronyze the queue
    virtual void Sync();
        /// add element to the queue
    virtual void AddElement(T);
        /// remove element to the queue
    virtual void RemElement(T);
    
public:
        /// Queue : Don't modify this list
    list<T> elements;

protected:
        // elements to add
    list<T> a_elements;
        // elements to remove
    list<T> r_elements;
};








/** The class which manages messages in the application. Generally,
    we have only one Looper in an application.
 */
class Stk_Looper
{
public:
        /// Constructor
    Stk_Looper();
        /// Destructor
    ~Stk_Looper();
    
        // Message functions
        /// Essential function: the Loop
    int Loop();
        /// Hook function: this functions send messages to messagequeue
    void StkPostMessage(Stk_Message *);


        /// Add a passive sender
    void AddPassiveSender(Stk_PassiveSender *);
		/// Rem a passive sender
	void RemPassiveSender(Stk_PassiveSender *);
        /// Add a prog
    void AddProg(Stk_Prog *);
        /// Rem a prog
    void RemProg(Stk_Prog *);
    
private:
        // Dispatch the message to handlers
    void Dispatch();

    list<Stk_Message *> messages;
    
        // the queue of progs
    Stk_Queue<Stk_Prog *> progs;

        // list of passive senders and his queue
    Stk_Queue<Stk_PassiveSender *> passivesenders;
};









/** The base class to receive Messages. A handler depends on a Looper.
    So don't use his destructor. The looper will do it. When you don't need
    this handler just call the "Quit" function.
 */
class Stk_Handler
{
public:
        /// Null constructor (No Looper & no father)
    Stk_Handler();
        /// Constructor with a looper (usefull for prog)
    Stk_Handler(Stk_Looper *);
        /// Constructor with an handler
    Stk_Handler(Stk_Handler *);
        /// Destructor: Don't use it
    virtual ~Stk_Handler();

        /// Add a son handler
    void AddHandler(Stk_Handler *);
        /// Rem a son handler
    void RemHandler(Stk_Handler *);
        // get focus (code executed when a prog becomes active)
        //    virtual void GetFocus();
        // loose focus
        //    virtual void LooseFocus();

        /// Redistribuate messages
    virtual void Dispatch(Stk_Message *);
        /// Hook function: When this handler receives a messages, it send to this function
    virtual void MessageReceived(Stk_Message *);
        /// Hook function: Send a message to this handler
    virtual void StkPostMessage(Stk_Message *);
        
    
    
protected:
        /// list of sons
    list<Stk_Handler *> handlers;
        /// a pointer on the looper which handler belongs to
    Stk_Looper *looper;
        /// father
    Stk_Handler *father;
};








/** This class is used to represent a prog on a stk system.
    There are tree functions to write: \\
    - Constructor: you place here what you must initialize \\
    - Loop: you place here what we are doing at each frame. To
    quit this program, we must return 0 else return something different 0\\
    - Destructor: this is simply the destructor \\
    Each class son of Stk_Prog must call the derivated constructor. We could
    say that it works like context. if we create in Loop() another class wich
    derivates from Stk_Prog, next frame the Loop() of this new class will be used.
    To return old program, just return 0 in the new loop function. \\
    WARNING: to create a prog, use the new operator. Don't create locally!!!
*/
class Stk_Prog: public Stk_Handler
{
public:
        /// the code to init this program
    Stk_Prog(Stk_Prog *);
        /// the first prog
    Stk_Prog(Stk_Looper *);
        /// get focus (code executed when a prog becomes active)
    virtual void GetFocus();
        /// loose focus
    virtual void LooseFocus();
        /// the delete code : don't call it explicit use loop with return -1
    virtual ~Stk_Prog();
    
        /// Hook function: When this handler receives a messages, it send to this function
    virtual void MessageReceived(Stk_Message *);
    
        /// the loop of program
    virtual int Loop();


};









/** This class is used to create messages sender that need
    time cpu. An exemple is the keyboard.
*/
class Stk_PassiveSender
{
public:
    Stk_PassiveSender();
    Stk_PassiveSender(Stk_Looper *);
            /// get focus (code executed when a prog becomes active)
    virtual void GetFocus();
        /// loose focus
    virtual void LooseFocus();

        /// hook function: generate events here
    virtual int Loop();
        /// send a message
    void StkPostMessage(Stk_Message *);

private:    
// a usefull pointer to send msg
    Stk_Looper *looper;    
};



#endif
