/***************************************************************************
 *   Copyright (C) 2003 by liuspider                                       *
 *   liuspider@users.sourceforge.net                                       *
 *                                                                         *
 *   This program 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 of the License, or     *
 *   (at your option) any later version.                                   *
 **************************************************************************/
#ifndef SOCKETSERVERTHREAD_H
#define SOCKETSERVERTHREAD_H

#include <map>

#define Uses_C_STDIO
#define Uses_SCIM_LOOKUP_TABLE
#define Uses_SCIM_SOCKET
#define Uses_SCIM_SOCKET_TRANSACTION
#define Uses_SCIM_CONFIG
#define Uses_SCIM_CONFIG_MODULE
#define Uses_SCIM_DEBUG

#include "config.h"
#include <scim.h>

#include <scim_panel.h>


#include <qthread.h>
#include <qobject.h>

#ifdef USE_SCIM_KDE_SETTINGS
#include "utils/scimkdesettings.h"
#endif

namespace scim{
// Declaration of internal data types.
enum __ClientType {
    UNKNOWN_CLIENT,
    FRONTEND_CLIENT,
    GUI_CLIENT
};

struct ClientInfo {
    uint32       key;
    __ClientType type;
};

typedef std::map<int, ClientInfo>                      ClientRepository;


class SocketServerThread : public QObject, public QThread
{
    Q_OBJECT
private:
    SocketServer       _socket_server;
    SocketTransaction  _send_transaction;
    SocketTransaction  _receive_transaction;
    String             _socket_address;
    int                _socket_timeout;

    int                _socket_client_count;

    int                _current_socket_client;
    uint32             _current_client_context;

    int                _last_socket_client;
    uint32             _last_client_context;

    uint32              _check_exit_timeout;
    bool                _should_exit;
    bool                _should_resident;
    ConfigPointer       scim_config;
    ConfigModule*       config_module;
    class KConfig *     config;
    ClientRepository    _client_repository;
    
private:
    bool x11FrontEndConnectSignalEmitted;
    void turn_on_panel ();
    void turn_off_panel();
    void update_display ();
    void update_screen ();
    void update_factory_info ();
    void update_spot_location ();
    void show_preedit_string ();
    void show_aux_string ();
    void show_lookup_table ();
    void hide_preedit_string ();
    void hide_aux_string ();
    void hide_lookup_table ();
    void update_preedit_string();
    void update_preedit_caret ();
    void update_aux_string ();
    void update_lookup_table ();
    
    void show_help();
    void show_factory_menu();
    bool check_client_connection( const Socket & );
    
    void socket_register_properties (int client);
    void socket_update_property (int client);

    void SocketCloseConnection (SocketServer *server, const Socket &client);
    ClientInfo SocketGetClientInfo (const Socket &client);
    bool SocketOpenConnection (SocketServer *server, const Socket &client);
signals:
    void guiClientDisconnected(int client);
    void x11FrontEndConnected();
    void lastConnectionFinished();
    void turnOnPanelReq();
    void turnOffPanelReq();
    void updateAuxStringReq( const QString &, const scim::AttributeList & );
    void updateDisplayReq( QString );
    void updateScreenReq( uint32 );
    void updateFactoryInfoReq( const QString &, const QString &);
    void registerProperties( const scim::PropertyList &, int);
    void updateProperty(const scim::Property&, int);
    void updateSpotLocationReq( int, int );
    void updatePreeditStringReq(const QString &, const scim::AttributeList &);
    void updateLookupTableReq( const QStringList &, const QStringList &, 
        QValueList<scim::AttributeList > &, int cursor,
        unsigned page_start, unsigned candidates, unsigned & exact_item_num );
    void showAuxStringReq();
    void showPreeditStringReq();
    void showStatusStringReq();
    void showFactoryMenu(std::vector <scim::String> & uuids, std::vector <scim::String> & names, 
      std::vector <scim::String> & langs, std::vector <scim::String> & icons);
    void showLookupTableReq();
    void showHelp(const QString &);
    void hidePreeditStringReq();
    void hideStatusStringReq();
    void hideAuxStringReq();
    void hideLookupTableReq();
    void updatePreeditCaretReq( int );
    void disconnectCompleted();

public:
    SocketServerThread( QObject *parent, QStringList & args );
    ~SocketServerThread();
    void AcceptConnection( SocketServer *, const Socket & );
    void ReceiveData( SocketServer *, const Socket & );
    void ExceptionHandler( SocketServer *, const Socket & );
    virtual void run();
    bool initSocketServer();
    void executeGUICommand();
public slots:
    virtual void Disconnect();
    void shutdown();
    void selectLookupTableItem(int);
    void lookupTablePageUp();
    void lookupTablePageDown();
    void activateProperty(int client, const scim::String & key);
    
    virtual void reloadScimConfig();
    virtual void getFactoryList();

    void getHelp();
    void changeFactory(const QString &);
};
}

#endif
