#ifndef IIIMP_ICSTATE_HH_
#define IIIMP_ICSTATE_HH_
#include <list>
#include <iiimp.h>
#include "basictype.hh"
#include "ICState.hh"
#include "IIIMP_hotkey.hh"
#include "IIIMP_IMState.hh"
#include "IMConnection.hh"
#include "IMInputContext.hh"
#include "IMSvr.hh"
#include "LEMgr.hh"

// State transition: N<->R<->W(<->R<->W...)

class IIIMP_ICState_REQUESTED;
class IIIMP_ICState : public ICState
{
    IIIMP_IMState *pims;
    LangIMList langimlist;
    
    virtual bool state_send_available_p()
    { return false; }

    virtual void destroy();

  protected:
    struct SharedState {
	bool conversion_mode;
	bool preedit;
	bool status;
	bool lookup_choice;
    };
    SharedState *pshared;
    IIIMP_hotkey *ihk;
    IIIMP_IMState *get_iiimp_imstate()
    { return (IIIMP_IMState*) get_imstate(); }

    bool send(
	IIIMP_message *pmes,
	bool deletep
    )
    { return get_iiimp_imstate()->send(pmes, deletep); }

    IIIMP_ICState_REQUESTED* start_request();

    IIIMP_ICState(
	CARD16BIT ic_id,
	IIIMP_IMState* piiims,
	ICHandler *pich,
	IMLExec_ICState *pimlex
    );

  public:
    iml_session_t *get_iml_session ();
    iml_methods_t *get_iml_methods ();

    IIIMPTrans* get_iiimptrans()
    { return get_iiimp_imstate()->get_iiimptrans(); }

    // IIIMP_hotkey_profile* get_hotkey_profile()
    // { return get_iiimp_imstate()->get_hotkey_profile(); }

    bool conversion_enable_p()
    { return pshared->conversion_mode; }

    IMLangList *get_langlist ();
    bool create_langimlist ();
    LangIMList *get_langimlist ();

    virtual bool message_proc(
	void *message
    );

    static IIIMP_ICState* create(
	CARD16BIT ic_id,
	IIIMP_IMState* piiims,
	ICHandler *pich
    );

    IMInputContext *get_iminputcontext ()
    {
	IMInputContext *pimic;
	pimic = dynamic_cast<IMInputContext *>(get_ichandler());
	return pimic;
    }
 
    IMSvr *get_imsvr ();
    LEMgr *get_lemgr ();

    virtual ~IIIMP_ICState();
  friend class IIIMP_hotkey;
};

class IIIMP_ICState_REQUESTED : public IIIMP_ICState
{

    IIIMP_ICState *pprev_state;

    // Restore REQUESTED->initial or prev WAITING state.
    bool finish();
    // Transit REQUESTED->WAITING state.
    bool wait(
	int opcode
    );
    bool wait_aux(
	int opcode,
	int index,
	u16string imname
    );
    bool wait_nested_message(
	int opcode,
	int listener_id,
	u16string filename
    );
    virtual bool state_send_available_p()
    { return true; }

  protected:
    IIIMP_message *preply;

  public:
    virtual bool message_proc(
	void *message
    );

    virtual bool dealing();

  public:
    // REQUEST functions.
    bool toggle_server_convmode(
	bool flag
    );
    bool process_read_ns_reply(
	IIIMP_message *pmes
    );
    bool set_values(
	IIIMP_message *pmes
    );
    bool toggle_icfocus(
	bool flag
    );
    bool reset();
    bool aux_setvalues(
	IIIMP_message *pmes
    );
    bool aux_getvalues(
	IIIMP_message *pmes
    );
    bool forward_event(
	IIIMP_message *pmes
    );
    bool forward_event_with_operations(
	IIIMP_message *pmes
    );
    bool destroyic();

  public:
    // IC operation handlers.
    virtual int toggle_client_convmode(
	bool flag
    );
    virtual int forward_keyevent(
	IMKeyEventStruct *pkeyevent
    );
    virtual int commit_string(
	IMText *pimtext
    );
    virtual int preedit_start();
    virtual int draw_preedit(
	IMPreeditDrawCallbackStruct *pimpdraw
    );
    virtual int preedit_done();
    virtual int status_start();
    virtual int draw_status(
	IMStatusDrawCallbackStruct *pimsdraw
    );
    virtual int status_done();
    virtual int lookup_start(
	IMLookupStartCallbackStruct *pimls
    );
    virtual int draw_lookup(
	IMLookupDrawCallbackStruct *pimld
    );
    virtual int lookup_process(
	IMLookupProcessCallbackStruct *pimlp
    );
    virtual int lookup_done();
    virtual int aux_start(
	IMAuxStartCallbackStruct *pimauxstart
    );
    virtual int draw_aux(
	IMAuxDrawCallbackStruct *pimauxdraw
    );
    virtual int aux_done(
	IMAuxDoneCallbackStruct *pimauxdone
    );
    virtual int read_ns(
	IMReadNSStruct *prns
    );

  public:
    IIIMP_ICState_REQUESTED(
	IIIMP_ICState *pbase
    );
};

class IIIMP_ICState_WAITING : public IIIMP_ICState
{
    IIIMP_ICState_REQUESTED *pstreq;
    int opcode;
    int index;
    u16string imname;
    int listener_id;
    u16string filename;
    bool wait_aux_message;
    bool wait_ns_message;

    void initialize()
    { index = -1; }
    bool waiting_aux_message_p()
    { return (index >= 0); }
    void restore_state();
    bool match_waiting_message(IIIMP_message *pmes);
    virtual bool state_send_available_p()
    { return false; }

  public:
    virtual bool message_proc(
	void *message
    );
    // waiting for a normal message.
    IIIMP_ICState_WAITING(
	IIIMP_ICState_REQUESTED *pbase,
	int opcode
    );
    // waiting for a AUX message.
    IIIMP_ICState_WAITING(
	IIIMP_ICState_REQUESTED *pbase,
	int opcode,
	int index,
	u16string imname
    );
    // waiting for a nested message.
    IIIMP_ICState_WAITING(
	IIIMP_ICState_REQUESTED *pbase,
	int opcode,
	u16string filename,
	int listener_id
    );
    virtual ~IIIMP_ICState_WAITING()
    {
	//TODO:we have to remove picsr if suddenly deleted...
    }
};

#endif /* not IIIMP_IMSTATE_HH_ */

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
