#ifndef KSIRCTOPLEVEL_H
#define KSIRCTOPLEVEL_H

#include <tqdatetime.h>
#include <tdemainwindow.h>

#include "ahistlineedit.h"
#include "messageReceiver.h"
#include "chanButtons.h"
#include "KSTicker/ksticker.h"
#include "ksircchannel.h"

#define KST_CHANNEL_ID 2

class KSircTopic;
class TQSplitter;
class KSircView;
class aListBox;
class UserControlMenu;
class ChannelParser;
class charSelector;
class LogFile;
class TDESelectAction;
class TQLabel;
class TQVBox;
class TQListBoxItem;

class TQPopupMenu;

class KSircTopLevel : public TDEMainWindow,
		      public UnicodeMessageReceiver
{
  TQ_OBJECT
  
    friend class ChannelParser;
public:
  /**
    * Constructor, needs the controlling ksircprocess passed to it, so
    * we can make the ksircmessage receiver happy.
    */
  KSircTopLevel(KSircProcess *_proc, const KSircChannel &channelInfo, const char *
		name=0);
  /**
    * Destructor, destroys itself.
    */
  ~KSircTopLevel();

  /**
    * Reimplement show() to popup the menu bars and toolbar items
    */
  virtual void show();

  /**
   * Line recieved that should be printed on the screen. Unparsed, and
   * ready processing.  This is a single line, and it NOT \n
   * terminated.
   */
  virtual void sirc_receive(TQString str, bool broadcast = false);

  /**
    * Reimplement the ksircmessagereceiver control messages.  These
    * are parsed and dealt with quickly.
    */
  virtual void control_message(int, TQString);

  TQWidget *lineEdit() const { return linee; }

  void setTopic( const TQString &topic );
  TQString topic() const { return m_topic; }

  /**
   * This returns the current channel information for a toplevel
   */
  const KSircChannel &channelInfo() const { return m_channelInfo; }

signals:
  /**
    * signals thats the toplevel widget wishes to
    * output a new line.  The line is correctly
    * linefeed terminated, etc.
    */
  void outputLine(TQCString);
  /**
    * open a new toplevel widget with for the
    * channel/user TQString.
    */
  void open_toplevel(const KSircChannel &);
  /**
    * emittedon shutdown, indicating that
    * this window is closing. Refrence to outselves
    * is include.
    */
  void closing(KSircTopLevel *, TQString channel);
  /**
   * emitted when the user typed /quit, will disconnect from this
   * server and close all toplevels belonging to it.
   */
  void requestQuit( const TQCString& command );
  /**
    * emitted when we change channel name
    * on the fly.  old is the old channel name, new
    * is the new one.
    */
  void changeChannel(const TQString &oldName, const TQString &newName);
  /**
    * emitted to say that KSircTopLevel
    * (this) is now the window with focus.  Used by
    * servercontroller to set the !default window.
    */
  void currentWindow(KSircTopLevel *);
  /**
   * Stop updating list item sizes, majour changes comming through
   *
   */
  void freezeUpdates(bool);
  /**
   * Emitted when a new message appeared in the irc window
   */
  void changed(bool, TQString);

public slots:
  /**
   * When enter is pressed, we read the SLE and output the results
   * after processing via emitting outputLine.
   */
  virtual void sirc_line_return(const TQString &s);

   /**
    * Clears the message window
    */
  void clearWindow();

  /**
   * If the focus shifts this should get called with
   * the widget that just got focus.  Used in MDI modes
   * where the toplevel doesn't get focus in/out events.
   */
  void focusChange(TQWidget *w);

protected slots:
    /**
      * When the rightMouse button is pressed in the nick list, popup
      * the User popup menu at his cursor location.
      */
   void UserSelected(int index);
   /**
     * Menu items was selected, now read the UserControlMenu and
     * reupdate the required menus.
     */
   void UserParseMenu(int id);
   /**
     * Page down accel key.  Tells the mainw to scroll down 1 page.
     */
   void AccelScrollDownPage();
   /**
     * Page Up accell key.  Tells the mainw to scroll down 1 page.
     */
   void AccelScrollUpPage();
   /**
     * Slot to termiate (close) the window.
     */
   void terminate() { close( true /*alsoDelete*/ ); }
   /**
     * Called when the user menu is finished and the popup menu needs
     * to be updated.
     */
   void UserUpdateMenu();
   /**
     * Open the new channel/window selector.
     */
   void newWindow();
   /**
     * We've received focus, let's make us the default, and issue a
     * /join such that we default to the right channel.
     */
   void gotFocus();
   /**
     * We've lost focus, set ourselves as loosing focus.
     */
   void lostFocus();
   /**
     * Create and popup the ticker.  Make sure to restore it to the
     * last position is was at.
     */
//   void showTicker();
   /**
     * toggle the timestamp from the channel window menu (and with keyaccel)
     */
   void toggleTimestamp();
   /**
     * toggle the filtering of join/part message
     */
   void toggleFilterJoinPart();

    /**
     * toggle the beep from the channel window menu (and with keyaccel)
     */
   void toggleBeep();

   /**
    * show the dcc manager
    */
   void showDCCMgr();

   /**
     * Delete the ticker and ppoup the main window
     */
//   void unHide();
   /**
     * On a TAB key press we call TabNickCompletion which
     * reads the last thing in linee matches it with a nick and
     * puts it back into the line.
     */
   void TabNickCompletionShift();
   /**
     * On a TAB key press we call TabNickCompletion which
     * reads the last thing in linee matches it with a nick and
     * puts it back into the line.
     */
   void TabNickCompletionNormal();

   /**
     * Signals a Line Change in linee
     */
   void lineeNotTab();
   /**
     *  Move the display to or from the root window
     *
     */
   void toggleRootWindow();
   /**
    * On a middle mouse button press we call pasteToWindow which
    * reads the clip board and pastes into the main listbox.
    */
   void pasteToWindow();
   /**
    * On a midle mouse button press to the nick list we open
    * a query window and paste the text there
    */
   void pasteToNickList(int button, TQListBoxItem *item, const TQPoint &pos);
   /**
    * dnd paste to nick list
    */
   void dndTextToNickList(const TQListBoxItem *itom, const TQString& text);
   /**
    * open a toplevel on double click
    */
   void openQueryFromNick(const TQString &);

   /**
    * Some text was dropped on the listbox
    */
   void slotTextDropped(const TQString&);

   /**
    * Calls slotDccURLs with the current nick we're talking to
    */
   void slotDropURLs(const TQStringList& urls);

   /**
    * Sends the list of urls to nick
    */
   void slotDccURLs(const TQStringList& urls, const TQString& nick );

   /**
    * Re-apply color settings.
    */
   void initColors();

   /**
   *  Dumps current content of mainw into a logfile
   */
   void saveCurrLog();

    /**
     * Makes a beep when a change happens (if the user has this on)
     * the bool is true if changed line contained user's nick
     */
   void doChange(bool, TQString);

   /**
    * show the ticker window
    */
   void toggleTicker();

   /**
    * ksirc command menu clicked on
    */
   void cmd_process(int id);

protected:
   /**
     * On a TAB key press we call TabNickCompletion which
     * reads the last thing in linee matches it with a nick and
     * puts it back into the line.
     */
   void TabNickCompletion(int dir);

   /**
    * Make sure to update colors correctly.
    */
   virtual bool event( TQEvent *e);

    /**
     * Redfine closeEvent to emit closing and delete itself.
     */
   virtual void closeEvent(TQCloseEvent *);
   /**
     * Searches through the nick list and finds the nick with the best match.
     * which, arg2, selects nicks other than the first shouldarg1 match more
     * than 1 nick.
     */
   virtual TQString findNick(TQString, uint which = 0);
   /**
    * remove a nick from the prefered in nick completion list
    */
   virtual void removeCompleteNick(const TQString &);
   /**
	* Adds a nick to the list of nicks to prefer in nick completion
	* or moves it to the top of the list if it was already there
	*/
   virtual void addCompleteNick(const TQString &);
   /**
	* Changes a nick in the completion list if it has been listed,
	* otherwise does nothing
	*/
   virtual void changeCompleteNick(const TQString &, const TQString &);

   virtual void setupCommandMenu();

   /**
    * Returns true if this window is a private conversation (query or dcc chat)
    *, instead of a public chat in a channel or a special window.
    */
   bool isPrivateChat() const;

   /**
    * Returns true if this is a public channel window
    */
   bool isPublicChat() const;

   /**
    * Returns true if this is a special window
    */
   bool isSpecialWindow() const;

private slots:
    void setTopicIntern( const TQString &topic );
    void insertText();
    void setMode(TQString, int, TQString currentNick=0);
    void setEncoding();
    void returnPressed();
    void toggleTopic();

private:

    void outputUnicodeLine( const TQString &message );

    bool atBottom();

    bool continued_line;
    charSelector *selector;
    chanButtons *channelButtons;
    TQSplitter *pan;
    TQVBox *nicks_box;
    TQVBox *top;
    KMenuBar *kmenu;
    TQLabel *lag;
    enum {PING = 10, TOPIC = 20};
    KSircView *mainw;
    aHistLineEdit *linee;
    aListBox *nicks;

    //TQString m_currentNick;

    //KSircProcess *proc;

    int lines;

    struct BufferedLine
    {
        BufferedLine() { wasBroadcast = false; }
        BufferedLine( const TQString &msg, bool broadc )
            { message = msg; wasBroadcast = broadc; }
        bool operator==( const BufferedLine &other )
            { return message == other.message &&
                wasBroadcast == other.wasBroadcast; }

        TQString message;
        bool wasBroadcast;
    };

  bool Buffer;
  TQValueList<BufferedLine> LineBuffer;

  // TQPopupMenu's used for the menubar
  TQPopupMenu *file, *edit, *command;

  bool parse_input(const TQString &string, TQString &plainText);
  void sirc_write(const TQString &str);

  TQPopupMenu *user_controls;
  static TQPtrList<UserControlMenu> *user_menu;
  int opami;

  TQAccel *accel;

  /**
   * The channel name that we belong too.
   */
  //TQString channel_name;

  /**
    * Caption at the top of the window.
    */
  TQString caption;
  /**
   * Current topic for the channel
   */
  TQString m_topic;

  /**
    * Does the window have focus? 1 when yes, 0 when no.
    */
  int have_focus;

  /**
    * Number of time tab has been pressed.  Each time it's pressed
    * roll through the list of matching nicks.
    */
  int tab_pressed;
  /**
   * When tabs pressed save the line for use at a latter date.
   * tab_nick holds the last nick found so when a blank tab is pressed
   * we pop the last niick and ": " up.
    */
  TQString tab_saved, tab_nick;
  int tab_start, tab_end;

  // Ticker specific variables.

  /**
    * Main pointer to ksticker.  Caution, it doesn't always exist!
    * Set to 0 ifwhen you delete it.
    */
  KSTicker *ticker;
  /**
    * Size and position of the main window. Main window is returns this
    * this position when it reappears.
    */
  TQRect myrect;
  /**
    * Position of the main window
    */
  TQPoint mypoint;
  /**
    * Ticker's size and geometry
    */
  TQRect tickerrect;
  /**
    * Tickers position
    */
  TQPoint tickerpoint;
  TQSize  tickersize;
  /**
   * Do we have a kick window open?
   * Remember not to open 2
   */
  bool KickWinOpen;

  /**
   * Hold an internal parser object which does all our parsing for us.
   * Since parsing an intergral part of TopLevel, it's also a friend
   * of ours
   */
  ChannelParser *ChanParser;

  /**
   * TQSize maintains size information in case it changes somehow
   */
  TQSize current_size;

  /**
   * ID of the timestamp menu item, to use in (un)checking it from slot
   */
  int tsitem;

  /**
   * ID of the filter join/part menu item, to use in (un)checking it from slot
   */
  int fjpitem;

  /**
   *  ID of the beep menu item, to use in (un)checking it from slot
   */
  int beepitem;

  /**
   * ID of the toggle topic menu item, to use in (un)checking it from slot
   */
  int topicitem;

  /**
   * ID of the show/hide ticker menu item
   */
  int tickeritem;

  /**
   * List of nicks already used in nick completion to give them
   * higher priority
   */
  TQStringList completeNicks;

  /**
   * The time of the last beep to prevent your soundcard from detonating
   * in high traffic channels
   */
  TQTime lastBeep;

  KSircTopic *ksTopic;

  LogFile *logFile;

  TDESelectAction *encodingAction;

  static TQStringList cmd_menu;

  bool m_gotMsgWithoutFocus;

  KSircChannel m_channelInfo;

};

#endif
