/*
  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) 2004-2006 Peter Simonsson <psn@linux.se>
  Copyright (C) 2006-2008 Eike Hein <hein@kde.org>
*/

#ifndef CHANNEL_H
#define CHANNEL_H

#include "server.h"
#include "chatwindow.h"
#include "channelnick.h"
#include "nick.h"

#include <tqtimer.h>
#include <tqstring.h>


class TQPushButton;
class TQCheckBox;
class TQLabel;
class TQTimer;
class TQListViewItem;
class TQHBox;
class TQStringList;
class TQSplitter;
class TQGrid;
class TQComboBox;
class TQDropEvent;
class TQToolButton;

class KLineEdit;

class NickListView;
class QuickButton;
class ModeButton;
class IRCInput;
class NickChangeDialog;

namespace Konversation
{
    class TopicLabel;
    class ChannelOptionsDialog;
}

class NickList : public TQPtrList<Nick>
{
    public:
        NickList();

        enum CompareMethod { AlphaNumeric, TimeStamp };

        TQString completeNick(const TQString& pattern, bool& complete, TQStringList& found,
                             bool skipNonAlfaNum, bool caseSensitive);

        void setCompareMethod(CompareMethod method);

        bool containsNick(const TQString& nickname);

    protected:
        virtual int compareItems(TQPtrCollection::Item item1, TQPtrCollection::Item item2);

    private:
        CompareMethod m_compareMethod;
};

class Channel : public ChatWindow
{
    TQ_OBJECT
  

    public:
        explicit Channel(TQWidget* parent, TQString name);
        ~Channel();
//META
        virtual bool canBeFrontView();
        virtual bool searchView();

        virtual void append(const TQString& nickname,const TQString& message);
        virtual void appendAction(const TQString& nickname,const TQString& message);
        void nickActive(const TQString& nickname);

//General administrative stuff
    public:
        void setName(const TQString& newName);
        TQString getPassword();

        const Konversation::ChannelSettings channelSettings();

        TQString getPassword() const;

        virtual void setServer(Server* newServer);
        void setIdentity(const IdentityPtr identity);

        void setEncryptedOutput(bool);

        bool joined() { return m_joined; }
        bool rejoinable();
//Unsure of future placement and/or continued existence of these members
        int numberOfNicks() const { return nicks; }
        int numberOfOps() const { return ops; }
        virtual void setChannelEncoding(const TQString& encoding);
        virtual TQString getChannelEncoding();
        virtual TQString getChannelEncodingDefaultDesc();
        virtual bool isInsertSupported() { return true; }

    protected:
        // use with caution! does not check for duplicates
        void fastAddNickname(ChannelNickPtr channelnick);
        void setActive(bool active);

    public slots:
        void setNickname(const TQString& newNickname);
        void scheduleAutoWho();
        void setAutoUserhost(bool state);
        void rejoin();

    protected slots:
        void autoUserhost();
        void autoWho();
        void fadeActivity();
        virtual void serverOnline(bool online);


//Nicklist
    public:
        ChannelNickPtr getOwnChannelNick();
        ChannelNickPtr getChannelNick(const TQString &ircnick);

        void joinNickname(ChannelNickPtr channelNick);
        void removeNick(ChannelNickPtr channelNick, const TQString &reason, bool quit);
        void kickNick(ChannelNickPtr channelNick, const TQString &kicker, const TQString &reason);
        void addNickname(ChannelNickPtr channelNick);
        void nickRenamed(const TQString &oldNick, const NickInfo& channelnick);
        void resetNickList();
        void addPendingNickList(const TQStringList& pendingChannelNickList);
        Nick *getNickByName(const TQString& lookname);
        NickList getNickList() { return nicknameList; }

        void adjustNicks(int value);
        void adjustOps(int value);
        virtual void emitUpdateInfo();

    protected slots:
        void purgeNicks();
        void processPendingNicks();

//Topic
    public:
        /** Get the current channel topic.
         *
         * The topic may or may not have the author that set it at the start of the string,
         * like:  "<author> topic"
         *
         * The internal variable topicAuthorUnknown stores whether the "<author>" bit is there or not.
         *
         * */
        TQString getTopic();
        /** Get the channel topic history sorted in reverse chronological order.
         *
         * Each topic may or may not have the author that set it at the start of the string,
         * like:  "<author> topic"
         *
         * @return a list of topics this channel used to have, current at the top.
         */
        TQStringList getTopicHistory();

        void setTopic(const TQString& topic);
        void setTopic(const TQString& nickname, const TQString& topic);
        void setTopicAuthor(const TQString& author, TQDateTime t);

    signals:
        void topicHistoryChanged();
        void joined(Channel* channel);


//Modes
//TODO: the only representation of the channel limit is held in the GUI

    public:
        /// Internal - Empty the modelist
        void clearModeList();
        /// Get the list of modes that this channel has - e.g. {+l,+s,-m}
        //TODO: does this method return a list of all modes, all modes that have been changed, or all modes that are +?
        TQStringList getModeList() const { return m_modeList; }

        /** Outputs a message on the channel, and modifies the mode for a ChannelNick.
         *  @param sourceNick The server or the nick of the person that made the mode change.
         *  @param mode The mode that is changing one of v,h,o,a for voice halfop op admin
         *  @param plus True if the mode is being granted, false if it's being taken away.
         *  @param parameter This depends on what the mode change is.  In most cases it is the nickname of the person that is being given voice/op/admin etc.  See the code.
         */
        void updateMode(const TQString& sourceNick, char mode, bool plus, const TQString &parameter);

    signals:
        void modesChanged();

//Bans
    public:

        void addBan(const TQString& ban);
        void removeBan(const TQString& ban);

        void clearBanList();
        TQStringList getBanList() const { return m_BanList; }

    signals:
        void banAdded(const TQString& newban);
        void banRemoved(const TQString& newban);
        void banListCleared();

//Generic GUI
    public:
        virtual bool eventFilter(TQObject* watched, TQEvent* e);

//Specific GUI
    public:
        void updateModeWidgets(char mode, bool plus, const TQString &parameter);
        void updateQuickButtons(const TQStringList &newButtonList);

        /// Get the contents of the input line.
        virtual TQString getTextInLine();
        /// Sounds suspiciously like a destructor..
        virtual bool closeYourself(bool askForConfirmation=true);

        bool autoJoin();

        ChannelNickList getSelectedChannelNicks();
        ///TODO: this looks like a half-arsed overload.
        TQStringList getSelectedNickList();

        NickListView* getNickListView() const { return nicknameListView; }

        Konversation::ChannelSettings channelSettings() const;

    signals:
        void sendFile();

    public slots:
        void updateAppearance();
        void channelTextEntered();
        void channelPassthroughCommand();
        void sendChannelText(const TQString& line);
        void showOptionsDialog();
        void showQuickButtons(bool show);
        void showModeButtons(bool show);

        void appendInputText(const TQString& s, bool fromCursor);
        virtual void indicateAway(bool show);
        void showTopic(bool show);
        void showNicknameBox(bool show);
        void showNicknameList(bool show);

        void setAutoJoin(bool autojoin);

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

    protected slots:
        void completeNick(); ///< I guess this is a GUI function, might be nice to have at DCOP level though --argonel
        void endCompleteNick();
        void filesDropped(TQDropEvent* e);
        void quickButtonClicked(const TQString& definition);
        void modeButtonClicked(int id,bool on);
        void channelLimitChanged();

        void popupChannelCommand(int id);         ///< Connected to IRCView::popupCommand()
        void popupCommand(int id);                ///< Connected to NickListView::popupCommand()
        void doubleClickCommand(TQListViewItem*);  ///< Connected to NickListView::doubleClicked()
        // Dialogs
        void changeNickname(const TQString& newNickname);

        void textPasted(const TQString& text); ///< connected to IRCInput::textPasted() - used to handle large/multiline pastings

        void sendFileMenu(); ///< connected to IRCInput::sendFile()
        void nicknameComboboxChanged();
        /// Enable/disable the mode buttons depending on whether you are op or not.
        void refreshModeButtons();

//only the GUI cares about sorted nicklists
        ///Request a delayed nicklist sorting
        void requestNickListSort();
        ///Sort the nicklist
        void sortNickList();

    protected:
        void showEvent(TQShowEvent* event);
        void syncSplitters();
        /// Called from ChatWindow adjustFocus
        virtual void childAdjustFocus();
        /// Close the channel then come back in
        void cycleChannel(); ///< TODO this is definately implemented and hooked incorrectly.

        bool channelCommand;///< True if nick context menu is executed from IRCView

        // to take care of redraw problem if hidden
        bool quickButtonsChanged;
        bool quickButtonsState;
        bool modeButtonsChanged;
        bool modeButtonsState;
        bool awayChanged;
        bool awayState;
        bool splittersInitialized;
        bool topicSplitterHidden;
        bool channelSplitterHidden;

        unsigned int completionPosition;

        TQSplitter* m_horizSplitter;
        TQSplitter* m_vertSplitter;
        TQWidget* topicWidget;
        TQToolButton* m_topicButton;
        Konversation::TopicLabel* topicLine;

        //TODO: abstract these
        TQHBox* modeBox;
        ModeButton* modeT;
        ModeButton* modeN;
        ModeButton* modeS;
        ModeButton* modeI;
        ModeButton* modeP;
        ModeButton* modeM;
        ModeButton* modeK;
        ModeButton* modeL;

        KLineEdit* limit; //TODO: this GUI element is the only storage for the mode

        NickListView* nicknameListView;
        TQHBox* commandLineBox;
        TQVBox* nickListButtons;
        TQGrid* buttonsGrid;
        TQComboBox* nicknameCombobox;
        TQString oldNick; ///< GUI
        TQLabel* awayLabel;
        TQLabel* blowfishLabel;
        IRCInput* channelInput;

        NickChangeDialog* nickChangeDialog;
        TQPtrList<QuickButton> buttonList;

//Members from here to end are not GUI
        bool m_joined;
        NickList nicknameList;
        TQTimer userhostTimer;

        TQStringList m_topicHistory;
        TQStringList m_BanList;
        bool topicAuthorUnknown; ///< Stores whether the "<author>" bit is there or not.

        bool m_firstAutoWhoDone;
        TQTimer m_whoTimer; ///< For continuous auto /WHO
        TQTimer m_fadeActivityTimer; ///< For the smoothing function used in activity sorting

        TQValueList<TQStringList> m_pendingChannelNickLists;
        int m_opsToAdd;
        uint m_currentIndex;

        TQTimer* m_processingTimer;
        TQTimer* m_delayedSortTimer;

        TQStringList m_modeList;
        ChannelNickPtr m_ownChannelNick;

        bool pendingNicks; ///< are there still nicks to be added by /names reply?
        int nicks; ///< How many nicks on the channel
        int ops; ///< How many ops on the channel

        Konversation::ChannelOptionsDialog *m_optionsDialog;
};
#endif
