/*
  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.
*/

/*
  Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
  Copyright (C) 2005 Ismail Donmez <ismail@kde.org>
  Copyright (C) 2005-2006 Peter Simonsson <psn@linux.se>
  Copyright (C) 2006-2008 Eli J. MacKenzie <argonel at gmail.com>
  Copyright (C) 2005-2008 Eike Hein <hein@kde.org>
*/

#ifndef SERVER_H
#define SERVER_H

#include "common.h"
#include "channelnick.h"
#include "inputfilter.h"
#include "outputfilter.h"
#include "nickinfo.h"
#include "sslsocket.h"
#include "serversettings.h"
#include "servergroupsettings.h"
#include "connectionsettings.h"

#include <tqtimer.h>
#include <tqvaluevector.h>
#include <tqguardedptr.h>

#include <ksharedptr.h>
#include <kprocess.h>
#include <tdesocketbase.h>
#include <kbufferedsocket.h>
#include <kstreamsocket.h>


class Channel;
class DccTransfer;
class DccTransferPanelItem;
class Query;
class StatusPanel;
class Identity;
class RawLog;
class ChannelListPanel;
class ScriptLauncher;
class ServerISON;
class TQStrList;
class ChatWindow;
class ViewContainer;

using namespace KNetwork;

class IRCQueue;

class Server : public TQObject
{
    TQ_OBJECT
  
    friend class IRCQueue;
    friend class QueueTuner;
void resetNickSelection();
    public:
        enum QueuePriority
        {
            LowPriority,      ///<slow queue, for automatic info gathering
            StandardPriority, ///<regular queue, for chat and user initiated commands
            HighPriority,     ///<for pongs and quits

            Howmanyqueuesdoweneedanywayquestionmark,

            HiPriority=HighPriority,
            LoPriority=LowPriority,
            NormalPriorty=StandardPriority,
            RegularPriority=StandardPriority
        };

        Server(TQObject* parent, ConnectionSettings& settings);
        ~Server();

        int connectionId() { return m_connectionId; }

        ConnectionSettings& getConnectionSettings() { return m_connectionSettings; }
        void setConnectionSettings(ConnectionSettings& settings) { m_connectionSettings = settings; }

        TQString getDisplayName() { return m_connectionSettings.name(); }
        TQString getServerName() { return m_connectionSettings.server().host(); }

        Konversation::ServerGroupSettingsPtr getServerGroup() { return m_connectionSettings.serverGroup(); }
        IdentityPtr getIdentity() { return m_connectionSettings.identity(); }

        Konversation::ConnectionState getConnectionState() { return m_connectionState; }

        bool isConnected() { return (m_connectionState == Konversation::SSConnected); }
        bool isConnecting() { return (m_connectionState == Konversation::SSConnecting); }

        bool getUseSSL() const;
        TQString getSSLInfo() const;
        int getPort();
        int getLag() const;

        void updateAutoJoin(Konversation::ChannelSettings channel = Konversation::ChannelSettings());

        void resetNickList(const TQString& channelName);
        void addPendingNickList(const TQString& channelName,const TQStringList& nickList);
        void addHostmaskToNick(const TQString &sourceNick, const TQString &sourceHostmask);
        Channel* nickJoinsChannel(const TQString &channelName, const TQString &nickname, const TQString &hostmask);
        void renameNick(const TQString &nickname,const TQString &newNick);
        Channel* removeNickFromChannel(const TQString &channelName, const TQString &nickname, const TQString &reason, bool quit=false);
        void nickWasKickedFromChannel(const TQString &channelName, const TQString &nickname, const TQString &kicker, const TQString &reason);
        void removeNickFromServer(const TQString &nickname, const TQString &reason);

        void setChannelTypes(const TQString &types);
        TQString getChannelTypes() const;

        // extended user modes support
        void setPrefixes(const TQString &modes, const TQString& prefixes);
        void mangleNicknameWithModes(TQString &nickname,bool& isAdmin,bool& isOwner,bool &isOp,
            bool& isHalfop,bool &hasVoice);

        bool isAChannel(const TQString &channel) const;
        bool isNickname(const TQString& compare) const;

        TQString getNickname() const;
        TQString loweredNickname() const;

        TQString getNextNickname();

        InputFilter* getInputFilter() { return &m_inputFilter; }
        Konversation::OutputFilter* getOutputFilter() { return m_outputFilter; };

        void joinChannel(const TQString& name, const TQString& hostmask);
        void removeChannel(Channel* channel);
        void appendServerMessageToChannel(const TQString& channel, const TQString& type, const TQString& message);
        void appendCommandMessageToChannel(const TQString& channel, const TQString& command, const TQString& message, bool highlight = true);
        void appendStatusMessage(const TQString& type,const TQString& message);
        void appendMessageToFrontmost(const TQString& type,const TQString& message, bool parseURL = true);

        int getPreLength(const TQString& command, const TQString& dest);

        void dcopRaw(const TQString& command);
        void dcopSay(const TQString& target,const TQString& command);
        void dcopInfo(const TQString& string);
        void ctcpReply(const TQString& receiver, const TQString& text);

        void setChannelTopic(const TQString& channel, const TQString& topic);
                                                  // Overloaded
        void setChannelTopic(const TQString& nickname, const TQString& channel, const TQString& topic);
        void updateChannelMode(const TQString& nick, const TQString& channel, char mode, bool plus, const TQString& parameter);
        void updateChannelModeWidgets(const TQString& channel, char mode, const TQString& parameter);

        Channel* getChannelByName(const TQString& name);
        Query* getQueryByName(const TQString& name);
        TQString parseWildcards(const TQString& toParse, const TQString& nickname, const TQString& channelName, const TQString &channelKey, const TQStringList &nickList, const TQString& parameter);
        TQString parseWildcards(const TQString& toParse, const TQString& nickname, const TQString& channelName, const TQString &channelKey, const TQString& nick, const TQString& parameter);

        void autoCommandsAndChannels();

        void sendURIs(const TQStrList& uris, const TQString& nick);

        void notifyAction(const TQString& nick);
        ChannelListPanel* getChannelListPanel() const;

        StatusPanel* getStatusView() const { return m_statusView; }
        virtual bool closeYourself(bool askForConfirmation=true);

        TQString getOwnIpByNetworkInterface();
        TQString getOwnIpByServerMessage();

        void requestAway(const TQString& reason = "");
        void requestUnaway();

        bool isAway() { return m_away; }
        void setAway(bool away);
        TQString awayTime() const;

        void setAwayReason(const TQString& reason) { m_awayReason = reason; }

        /**
         * Returns true if the given nickname is known to be online.
         * @param nickname      The nickname.  Case insensitive.
         * @return              True if the nickname is known to be online by the server.
         * Note that a nick that is not in any of the joined channels and is not on the
         * notify list, and has not initiated a query with you, may well be online,
         * but server doesn't know if it is or not, in which case False is returned.
         */
        bool isNickOnline(const TQString &nickname);
        /** Given a nickname, returns NickInfo object.
         *  @param nickname    The desired nickname.  Case insensitive.
         *  @return            Pointer to the nickinfo for this nickname if one exists.
         *                     0 if not known to be online.
         *
         *  A NickInfo pointer will only be returned if the nickname is known to the Konvi
         *  Server object.  A nick will be known if:
         *  - It is in one of the server's channels user has joined.
         *  - It is on the notify list and is known to be online.
         *  - The nick initiated a query with the user.
         *  A NickInfo is destroyed when it is offline.
         */
        NickInfoPtr getNickInfo(const TQString& nickname);
        /** Given a nickname, returns an existing NickInfo object, or creates a new NickInfo object.
         *  Guaranteed to return a nickinfo.
         *  @param nickname    The desired nickname.  Case sensitive.
         *  @return            Pointer to the found or created NickInfo object.
         */
        NickInfoPtr obtainNickInfo(const TQString& nickname);
        /** Returns a list of all the NickInfos that are online and known to the server.
         * Caller should not modify the list.
         * A nick will be known if:
         *  - It is in one of the server's channels user has joined.
         *  - It is on the notify list and is known to be online.
         *  - The nick initiated a query with the user.
         *
         * @return A TQMap of TDESharedPtrs to NickInfos indexed by lowercase nickname.
         */
        const NickInfoMap* getAllNicks();
        /** Returns the list of members for a channel in the joinedChannels list.
         *  A joinedChannel is one that you are in, as opposed to a channel that you aren't in,
         *  but one of your watched nicks is in.
         *  Code that calls this must not modify the list.
         *  @param channelName Name of desired channel.  Case insensitive.
         *  @return            A map of all the nicks in the channel.
         *                     0 if channel is not in the joinedChannels list.
         */
        const ChannelNickMap *getJoinedChannelMembers(const TQString& channelName) const;
        /** Returns the list of members for a channel in the unjoinedChannels list.
         *  An unjoinedChannel is a channel you aren't in.  As such, this is only going to return
         *  nicks that you know are in that channel because a /whois has been done against them.
         *  This could be done automatically if they are on the watch list.
         *  Code that calls this must not modify the list.
         *  @param channelName Name of desired channel.  Case insensitive.
         *  @return            A map of only the nicks that we know that are in the channel.
         *                     0 if channel is not in the unjoinedChannels list.
         */
        const ChannelNickMap *getUnjoinedChannelMembers(const TQString& channelName) const;
        /** Searches the Joined and Unjoined lists for the given channel and returns the member list.
         *  Code that calls this must not modify the list.
         *  @param channelName Name of desired channel.  Case insensitive.
         *  @return            A map of nicks in that channel.  0 if channel is not in either list.
         *
         *  @see getJoinedChannelMembers(const TQString& channelName)
         *  @see getUnjoinedChannelMembers(const TQString& channelName)
         */
        const ChannelNickMap *getChannelMembers(const TQString& channelName) const;
        /** Returns a list of all the joined channels that a nick is in.
         *  @param nickname    The desired nickname.  Case insensitive.
         *  @return            A list of joined channels the nick is in.  Empty if none.
         */
        TQStringList getNickJoinedChannels(const TQString& nickname);
        /** Returns a list of all the channels (joined or unjoined) that a nick is in.
         *  @param nickname    The desired nickname.  Case insensitive.
         *  @return            A list of channels the nick is in.  Empty if none.
         *
         *  A nick will not appear in the Unjoined channels list unless a WHOIS
         *  has been performed on it.
         */
        TQStringList getNickChannels(const TQString& nickname);
        /** Returns pointer to the ChannelNick (mode and pointer to NickInfo) for a
         *  given channel and nickname.
         *  @param channelName The desired channel name.  Case insensitive.
         *  @param nickname    The desired nickname.  Case insensitive.
         *  @return            Pointer to ChannelNick structure containing a pointer
         *                     to the NickInfo and the mode of the nick in the channel.
         *                     0 if not found.
         */
        ChannelNickPtr getChannelNick(const TQString& channelName, const TQString& nickname);
        /** Updates a nickname in a channel.  If not on the joined or unjoined lists, and nick
         *  is in the watch list, adds the channel and nick to the unjoinedChannels list.
         *  If mode != 99, sets the mode for the nick in the channel.
         *  Returns the NickInfo object if nick is on any lists, otherwise 0.
         *  @param channelName The channel name.  Case sensitive.
         *  @param nickname    The nickname.  Case sensitive.
         *  @param mode        Bit mask containing the modes the nick has in the channel,
         *                     or 99 if not known.  See channelnick.cpp for bit definitions.
         */
        ChannelNickPtr setChannelNick(const TQString& channelName, const TQString& nickname, unsigned int mode = 99);
        /**
         * Given the nickname of nick that is offline (or at least not known to be online),
         * returns the addressbook entry (if any) for the nick.
         * @param nickname       Desired nickname.  Case insensitive.
         * @return               Addressbook entry of the nick or empty if not found.
         */
        TDEABC::Addressee getOfflineNickAddressee(TQString& nickname);

        /**
         * Returns a TQPtrList of all channels
         */
        const TQPtrList<Channel>& getChannelList() const { return m_channelList; }

        void emitChannelNickChanged(const ChannelNickPtr channelNick);
        void emitNickInfoChanged(const NickInfoPtr nickInfo);

        /**
         * Returns a list of all the nicks on the user watch list plus nicks in the addressbook.
         */
        TQStringList getWatchList();
        TQString getWatchListString();
        /**
         * Return true if the given nickname is on the watch list.
         */
        bool isWatchedNick(const TQString& nickname);
        /**
         * Returns a list of all the nicks on the watch list that are not in joined
         * channels.  ISON command is sent for these nicks.
         */
        TQStringList getISONList();
        TQString getISONListString();

        ViewContainer* getViewContainer() const;

        /** Adds a nickname to the joinedChannels list.
         *  Creates new NickInfo if necessary.
         *  If needed, moves the channel from the unjoined list to the joined list.
         *  If needed, moves the nickname from the Offline to Online lists.
         *  If mode != 99 sets the mode for this nick in this channel.
         *  @param channelName The channel name.  Case sensitive.
         *  @param nickname    The nickname.  Case sensitive.
         *  @return            The NickInfo for the nickname.
         */
        ChannelNickPtr addNickToJoinedChannelsList(const TQString& channelName, const TQString& nickname);

        void setAllowedChannelModes(const TQString& modes) { m_allowedChannelModes = modes; }
        TQString allowedChannelModes() const { return m_allowedChannelModes; }

        void registerWithServices();

        // Blowfish stuff
        TQCString getKeyForRecipient(const TQString& recipient) const;
        void setKeyForRecipient(const TQString& recipient, const TQCString& key);

        bool identifyMsg() const { return m_identifyMsg; }

        ChannelListPanel* addChannelListPanel();

        // invoked by DccTransferSend
        void dccSendRequest(const TQString& recipient,const TQString& fileName,const TQString& address,const TQString& port,unsigned long size);
        void dccPassiveSendRequest(const TQString& recipient,const TQString& fileName,const TQString& address,unsigned long size,const TQString& token);
        // invoked by DccTransferRecv
        void dccResumeGetRequest(const TQString& sender,const TQString& fileName,const TQString& port,TDEIO::filesize_t startAt);
        void dccReverseSendAck(const TQString& partnerNick,const TQString& fileName,const TQString& ownAddress,const TQString& ownPort,unsigned long size,const TQString& reverseToken);

    // IRCQueueManager
        bool validQueue(QueuePriority priority); ///< is this queue index valid?
        void resetQueues(); ///< Tell all of the queues to reset
        static int _max_queue() { return Howmanyqueuesdoweneedanywayquestionmark-1; }

        /** Forces the queued data to be sent in sequence of age, without pause.

            This could flood you off but since you're quitting, we probably don't care. This is done
            here instead of in the queues themselves so we can interleave the queues without having to
            zip the queues together. If you want to quit the server normally without sending, reset the queues
            first.
         */
        void flushQueues();

        //These are really only here to limit where ircqueue.h is included
        static void _fetchRates(); ///< on server construction
        static void _stashRates(); ///< on application exit
        static void _resetRates(); ///< when QueueTuner says to


    signals:
        void destroyed(int connectionId);
        void nicknameChanged(const TQString&);
        void serverLag(Server* server,int msec);  /// will be connected to KonversationMainWindow::updateLag()
        void tooLongLag(Server* server, int msec);/// will be connected to KonversationMainWindow::updateLag()
        void resetLag(); ///< will be emitted when new 303 came in
        void nicksNowOnline(Server* server,const TQStringList& list,bool changed);
        void awayState(bool away);                /// will be connected to any user input panel;
        void multiServerCommand(const TQString& command, const TQString& parameter);

        /**
         * Emitted when the server gains/loses connection.
         * Will be connected to all server dependant tabs.
         */
        void serverOnline(bool state);

        /**
         * Emitted every time something gets sent.
         *
         *  @param  bytes           The count of bytes sent to the server, before re-encoding.
         *  @param  encodedBytes    The count of bytes sent to the server after re-encoding.
         */
        void sentStat(int bytes, int encodedBytes, IRCQueue *whichQueue);
        //FIXME can anyone who can connect to a Server signal not know about an IRCQueue?
        void sentStat(int bytes, int encodedBytes);

        //Note that these signals haven't been implemented yet.
        /// Fires when the information in a NickInfo object changes.
        void nickInfoChanged(Server* server, const NickInfoPtr nickInfo);

        /// Fires when the mode of a nick in a channel changes.
        void channelNickChanged(Server* server, const ChannelNickPtr channelNick);

        /// Fires when a nick leaves or joins a channel.  Based on joined flag, receiver could
        /// call getJoinedChannelMembers or getUnjoinedChannelMembers, or just
        /// getChannelMembers to get a list of all the nicks now in the channel.
        /// parted indicates whether the nick joined or left the channel.
        void channelMembersChanged(Server* server, const TQString& channelName, bool joined, bool parted, const TQString& nickname);

        /// Fires when a channel is moved to/from the Joinied/Unjoined lists.
        /// joined indicates which list it is now on.  Note that if joined is False, it is
        /// possible the channel does not exist in any list anymore.
        void channelJoinedOrUnjoined(Server* server, const TQString& channelName, bool joined);

        /// Fires when a nick on the watch list goes online or offline.
        void watchedNickChanged(Server* server, const TQString& nickname, bool online);
        ///Fires when the user switches his state to away and has enabled "Insert Remember Line on away" in his identity.
        void awayInsertRememberLine(Server* server);
        void sslInitFailure();
        void sslConnected(Server* server);

        void connectionStateChanged(Server* server, Konversation::ConnectionState state);

        void showView(ChatWindow* view);
        void addDccPanel();
        void addDccChat(const TQString& myNick,const TQString& nick,const TQStringList& arguments,bool listen);

    public slots:
        void connectToIRCServer();

        /** Adds line to queue if non-empty. */
        bool queue(const TQString& line, QueuePriority priority=StandardPriority);
        //TODO this should be an overload, not a separate name. ambiguous cases need TQString() around the cstring
        bool queueList(const TQStringList& buffer, QueuePriority priority=StandardPriority);

        void setNickname(const TQString &newNickname);
        /** This is called when we want to open a new query, or focus an existing one.
         *  @param nickInfo The nickinfo we want to open the query to.  Must exist.
         *  @param weinitiated This is whether we initiated this - did we do /query, or somebody else sending us a message.
         *  @return A pointer to a new or already-existing query.  Guaranteed to be non-null
         */
        Query *addQuery(const NickInfoPtr & nickInfo, bool weinitiated);
        void closeQuery(const TQString &name);
        void closeChannel(const TQString &name);
        void quitServer();
        void openDccChat(const TQString& nickname);
        void requestDccChat(const TQString& partnerNick, const TQString& numericalOwnIp, const TQString& ownPort);
        void requestBan(const TQStringList& users,const TQString& channel,const TQString& option);
        void requestUnban(const TQString& mask,const TQString& channel);

        void addDccSend(const TQString &recipient,KURL fileURL, const TQString &altFileName = TQString(), uint fileSize = 0);
        void removeQuery(Query *query);
        void startNotifyTimer(int msec=0);
        void sendJoinCommand(const TQString& channelName, const TQString& password = TQString());
        void requestChannelList();
        void requestWhois(const TQString& nickname);
        void requestWho(const TQString& channel);
        void requestUserhost(const TQString& nicks);
        void requestTopic(const TQString& channel);
        void resolveUserhost(const TQString& nickname);
        void addRawLog(bool show);
        void closeRawLog();
        void addToChannelList(const TQString& channel, int users, const TQString& topic);
        void closeChannelListPanel();
        void updateChannelQuickButtons();
        void sendMultiServerCommand(const TQString& command, const TQString& parameter);
        void executeMultiServerCommand(const TQString& command, const TQString& parameter);
        void reconnect();
        void disconnect(); //FIXME is this overriding a qobject method? do we care?
        void showSSLDialog();
        void sendToAllChannels(const TQString& text);
        void notifyTimeout();

        void enableIdentifyMsg(bool enabled);
        bool identifyMsgEnabled();
        void addBan(const TQString &channel, const TQString &ban);
        void removeBan(const TQString &channel, const TQString &ban);

        /// Called when we received a PONG from the server
        void pongReceived();

    protected slots:
        void lookupFinished();
        void preShellCommandExited(TDEProcess*);
        void ircServerConnectionSuccess();
        void startAwayTimer();
        void incoming();
        void processIncomingData();
        /// Sends the TQString to the socket. No longer has any internal concept of queueing
        void toServer(TQString&, IRCQueue *);
        /// Because TDEBufferedSocket has no closed(int) signal we use this slot to call broken(0)
        void closed();
        void broken(int state);
        /** This is connected to the SSLSocket failed.
         * @param reason The reason why this failed.  This is already translated, ready to show the user.
         */
        void sslError(const TQString& reason);
        void connectionEstablished(const TQString& ownHost);
        void notifyResponse(const TQString& nicksOnline);
        void slotNewDccTransferItemQueued(DccTransfer* transfer);
        void startReverseDccSendTransfer(const TQString& sourceNick,const TQStringList& dccArguments);
        void addDccGet(const TQString& sourceNick,const TQStringList& dccArguments);
        void requestDccSend();                    // -> to outputFilter, dccPanel
                                                  // -> to outputFilter
        void requestDccSend(const TQString& recipient);
                                                  // -> to inputFilter
        void resumeDccGetTransfer(const TQString& sourceNick,const TQStringList& dccArguments);
                                                  // -> to inputFilter
        void resumeDccSendTransfer(const TQString& sourceNick,const TQStringList& dccArguments);
        void dccGetDone(DccTransfer* item);
        void dccSendDone(DccTransfer* item);
        void dccStatusChanged(DccTransfer* item, int newStatus, int oldStatus);
        void scriptNotFound(const TQString& name);
        void scriptExecutionError(const TQString& name);
        void userhost(const TQString& nick,const TQString& hostmask,bool away,bool ircOp);
        void setTopicAuthor(const TQString& channel,const TQString& author, TQDateTime t);
        void endOfWho(const TQString& target);
        void invitation(const TQString& nick,const TQString& channel);
        void sendToAllChannelsAndQueries(const TQString& text);
        void gotOwnResolvedHostByWelcome(KResolverResults res);
        void gotOwnResolvedHostByUserhost(KResolverResults res);

        /// Send a PING to the server so we can meassure the lag
        void sendPing();
        /// Updates GUI when the lag gets high
        void updateLongPongLag();

        /// Update the encoding shown in the mainwindow's actions
        void updateEncoding();

    private slots:
        void collectStats(int bytes, int encodedBytes);

        /** Called in the server constructor if the preferences are set to run a command on a new server instance.
         *  This sets up the kprocess, runs it, and connects the signals to call preShellCommandExited when done. */
        void doPreShellCommand();

    protected:
        // constants
        static const int BUFFER_LEN=513;

        /// Initialize the timers
        void initTimers();

        /// Connect to the signals used in this class.
        void connectSignals();

        int _send_internal(TQString outputline); ///< Guts of old send, isn't a slot.

        /** Adds a nickname to the unjoinedChannels list.
         *  Creates new NickInfo if necessary.
         *  If needed, moves the channel from the joined list to the unjoined list.
         *  If needed, moves the nickname from the Offline to the Online list.
         *  If mode != 99 sets the mode for this nick in this channel.
         *  @param channelName The channel name.  Case sensitive.
         *  @param nickname    The nickname.  Case sensitive.
         *  @return            The NickInfo for the nickname.
         */
        ChannelNickPtr addNickToUnjoinedChannelsList(const TQString& channelName, const TQString& nickname);

        /**
         * If not already online, changes a nick to the online state by creating
         * a NickInfo for it and emits various signals and messages for it.
         * This method should only be called for nicks on the watch list.
         * @param nickname           The nickname that is online.
         * @return                   Pointer to NickInfo for nick.
         */
        NickInfoPtr setWatchedNickOnline(const TQString& nickname);

        /**
        * Display offline notification for a certain nickname. The function doesn't change NickInfo objects.
        * If NickInfoPtr is given, then also the integration with KAddressBook is engaged (i.e. the
        * nick is marked as away)
        * @param nickname           The nickname that is offline
        * @param nickInfo           Pointer to NickInfo for nick
        */
        void setWatchedNickOffline(const TQString& nickname, const NickInfoPtr nickInfo);

        /**
         * If nickname is no longer on any channel list, or the query list, delete it altogether.
         * Call this routine only if the nick is not on the notify list or is on the notify
         * list but is known to be offline.
         * @param nickname           The nickname to be deleted.  Case insensitive.
         * @return                   True if the nickname is deleted.
         */
        bool deleteNickIfUnlisted(const TQString &nickname);

        /**
         * If not already offline, changes a nick to the offline state.
         * Removes it from all channels on the joined and unjoined lists.
         * If the nick is in the watch list, and went offline, emits a signal,
         * posts a Notify message, and posts a KNotify.
         * If the nick is in the addressbook, and went offline, informs addressbook of change.
         * If the nick goes offline, the NickInfo is deleted.
         *
         * @param nickname     The nickname.  Case sensitive.
         * @return             True if the nick was online.
         */
        bool setNickOffline(const TQString& nickname);

        /** Remove nickname from a channel (on joined or unjoined lists).
         *  @param channelName The channel name.  Case insensitive.
         *  @param nickname    The nickname.  Case insensitive.
         */
        void removeChannelNick(const TQString& channelName, const TQString& nickname);

        /** Remove channel from the joined list.
         *  Nicknames in the channel are added to the unjoined list if they are in the watch list.
         *  @param channelName The channel name.  Case insensitive.
         */
        void removeJoinedChannel(const TQString& channelName);

        /** Renames a nickname in all NickInfo lists.
         *  @param nickInfo    Pointer to existing NickInfo object.
         *  @param newname     New nickname for the nick.  Case sensitive.
         */
        void renameNickInfo(NickInfoPtr nickInfo, const TQString& newname);

        bool getAutoJoin() const;
        void setAutoJoin(bool on);

        TQStringList getAutoJoinCommands() const { return m_autoJoinCommands; }
        void setAutoJoinCommands(const TQStringList& commands) { m_autoJoinCommands = commands; }

        unsigned int m_completeQueryPosition;
        TQValueList<int> m_nickIndices;
        TQStringList m_referenceNicklist;

        // TODO roll these into a TQMap.
        TQString m_serverNickPrefixes;               // Prefixes used by the server to indicate a mode
        TQString m_serverNickPrefixModes;            // if supplied: modes related to those prefixes
        TQString m_channelPrefixes;                  // prefixes that indicate channel names. defaults to RFC1459 "#&"

        bool m_autoJoin;

        TQStringList m_autoJoinCommands;

        KNetwork::KStreamSocket* m_socket;

        TQTimer m_reconnectTimer;
        TQTimer m_incomingTimer;
        TQTimer m_notifyTimer;
        TQStringList m_notifyCache;                  // List of users found with ISON
        int m_checkTime;                            // Time elapsed while waiting for server 303 response
        int m_currentLag;

        TQCString m_inputBufferIncomplete;
        TQStringList m_inputBuffer;

        TQValueVector<IRCQueue *> m_queues;
        int m_bytesSent, m_encodedBytesSent, m_linesSent, m_bytesReceived;

        TQString m_nickname;
        TQString m_loweredNickname;
        TQString m_ownIpByUserhost;                  // RPL_USERHOST
        TQString m_ownIpByWelcome;                   // RPL_WELCOME

        TQPtrList<Channel> m_channelList;
        TQPtrList<Query> m_queryList;

        InputFilter m_inputFilter;
        Konversation::OutputFilter* m_outputFilter;

        TQGuardedPtr<StatusPanel> m_statusView;
        TQGuardedPtr<RawLog> m_rawLog;
        TQGuardedPtr<ChannelListPanel> m_channelListPanel;

        bool m_away;
        TQString m_awayReason;
        TQString m_nonAwayNick;
        int m_awayTime;

        Konversation::ConnectionState m_connectionState;
        void updateConnectionState(Konversation::ConnectionState state);
        bool isSocketConnected() const;

        ScriptLauncher* m_scriptLauncher;

        TDEProcess m_preShellCommand;

    private:
        /// Helper object to construct ISON (notify) list and map offline nicks to
        /// addressbook.
        ServerISON* m_serverISON;
        /// All nicks known to this server.  Note this is NOT a list of all nicks on the server.
        /// Any nick appearing in this list is online, but may not necessarily appear in
        /// any of the joined or unjoined channel lists because a WHOIS has not yet been
        /// performed on the nick.
        NickInfoMap m_allNicks;
        /// List of membership lists for joined channels.  A "joined" channel is a channel
        /// that user has joined, i.e., a tab appears for the channel in the main window.
        ChannelMembershipMap m_joinedChannels;
        /// List of membership lists for unjoined channels.  These come from WHOIS responses.
        /// Note that this is NOT a list of all channels on the server, just those we are
        /// interested in because of nicks in the Nick Watch List.
        ChannelMembershipMap m_unjoinedChannels;
        /// List of nicks in Queries.
        NickInfoMap m_queryNicks;

        TQString m_allowedChannelModes;

        // Blowfish key map
        TQMap<TQString,TQCString> m_keyMap;

        bool m_identifyMsg;
        bool m_autoIdentifyLock;

        /// Used to lock incomingTimer while processing message.
        bool m_processingIncoming;

        /// Meassures the lag between PING and PONG
        TQTime m_lagTime;
        /// Updates the gui when the lag gets too high
        TQTimer m_pingResponseTimer;

        /// Previous ISON reply of the server, needed for comparison with the next reply
        TQStringList m_prevISONList;

        ConnectionSettings m_connectionSettings;

        static int m_availableConnectionId;
        int m_connectionId;
};

#endif
