/***************************************************************************
                          dchubsearch.h  -  description
                             -------------------
    begin                : Fri Mar 15 2002
    copyright            : (C) 2002-2004 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 DCHUBSEARCH_H
#define DCHUBSEARCH_H

/**
 *@author Mathias Küster
 */

#include <QTimer>
#include <QList>
#include <QHash>
#include <QMutex>
#include <QString>
#include <QCloseEvent>
#include <QFile>
#include <QWidget>

#include "DCDialogHubSearch.h"
#include "dcgui.h"
#include "dcconnectionmanager.h"
#include "searchresultmodel.h"

class CMessageSearchResult;
class CDCMessage;
class CMessageLog;

/* could also switch to QList */
#include <dclib/core/types.h>
#include <dclib/core/clist.h>

/* _CCallback1 is a template class so forward decls don't really work */
#include <dclib/core/ccallback.h>

class DC_ListResult;

class QMdiSubWindow;
class QEvent;
class QResizeEvent;
class QShowEvent;

/**
 * Need to keep track of CSearchManager state which
 * may be changed by auto search or another search window.
 *
 * READY = no search is running (which window last used CSearchManager does not matter)
 * SEARCH = our search is running
 * OTHER = another search window is searching
 * AUTO = the auto search is running ("external" search)
 */
enum eGlobalSearchState {
    egssREADY,
    egssSEARCH,
    egssOTHER,
    egssAUTO
};

class DCWaitMagnet : public QWidget {
    Q_OBJECT

    /**
        @author Dmitry Krivomasov
     */

public:

    DCWaitMagnet(QWidget * parent = 0);
    virtual ~DCWaitMagnet();
    void showMagnet(QString tth);

    /** */
    static void SetInstance(DCWaitMagnet *);
    /** */
    static DCWaitMagnet *Instance();

protected:
    void timerEvent(QTimerEvent *event);

private:
    int timerId;
    void testFile();
    QFile *file;
    QString magnet;
    QString key;

    static DCWaitMagnet *pWaitMagnet;
};

/** */
inline void DCWaitMagnet::SetInstance(DCWaitMagnet *wmagnet) {
    pWaitMagnet = wmagnet;
}

/** */
inline DCWaitMagnet *DCWaitMagnet::Instance() {
    return pWaitMagnet;
}

class DCHubSearch : public QWidget, private Ui::DCDialogHubSearch {
    Q_OBJECT

public:
    typedef QHash<QString, QString> QStringHash;
    /** construtor */
    DCHubSearch(QWidget * parent = 0);
    /** destructor */
    virtual ~DCHubSearch();

    /** Get the MDI sub window we are in */
    QMdiSubWindow * GetMdiSubWindow() {
        return m_pContainerWindow;
    }

    /** search result */
    bool DC_SearchResult(CMessageSearchResult * MessageSearchResult);

    /** callback function */
    int DC_CallBack(CDCMessage *);

    /** For searching from chat / transfer view */
    void SetSearchForFile(QString file, eFileTypes filetype = eftALL, int sizepos = 0, ulonglong size = 0);
    /** To start search from another window prompting if another search is running */
    void StartSearchWithPrompt();

    /** */
    static void InitCompleterDict();
    /** */
    static void DeInitCompleterDict();
    /** */
    static QStringList *GetCompleterDict();

    /** Move focus to lineEdit_SEARCHSTR*/
    void raiseFocus();

protected:
    /** Adjust column sizes preserving user set size ratios */
    void SizeColumnsPreservingRatios();
    /** resize event handler */
    virtual void resizeEvent(QResizeEvent *);
    /** overridden so that the column widths are initialized on first show() */
    virtual void showEvent(QShowEvent * event);
    /** event filter */
    virtual bool eventFilter(QObject * object, QEvent * event);
    /** */
    virtual void closeEvent(QCloseEvent *e);

private:
    /** */
    void InitDocument();
    /** */
    void DeInitDocument();
    /** */
    QString GetSearchQueryString();
    /** */
    static QStringHash &GetDownloadDirs();
    /** show all search results */
    void ShowResults(bool bClearList);
    /** */
    void SetSearchView(bool enabled);
    /** get the search string with protocol */
    CDCMessage * GetSearchObject();
    /** */
    void ShowSearchResult(CMessageSearchResult * MessageSearchResult);

    /**
     * Clearing the search results list also requires
     * clearing the hash used for grouping and zeroing the empty group pointer.
     */
    void ClearSearchResults();

    /** */
    void RemoveSelectedSearch(QList<QTreeWidgetItem*> *);

    /** */
    void startSearch();
    /** */
    void addHistory(CDCMessage * msg = 0);
    /** Needed both for right-click and double-click */
    void DownloadFolder(const QString &, const QString &, const QString &, const QString &, const QString &);
    /**
     * For saving the settings so new hubs will use them
     * without closing this hubs.
     */
    void saveColumns();

    /** store all messages from udp socket */
    CList<CDCMessage> * m_pMessageList;
    /** */
    CList<CDCMessage> * m_pSearchQueryList;
    /** store all search results */
    CList<CMessageSearchResult> * m_pSearchResultList;
    /** search history */
    CList<CDCMessage> * m_pSearchHistory;
    /** */
    QMutex SocketCallbackMutex;
    /** */
    QTimer m_Timer;
    /** current CSearchManager state */
    eGlobalSearchState m_eSearchState;
    /** */
    QMdiSubWindow * m_pContainerWindow;
    /** The last width that we adjusted the size of the file search result columns for */
    int lastFileResultsWidth;
    /** The last width that we adjusted the size of the user search result columns for */
    int lastUserResultsWidth;
    /**
     * Our callback function which we give to CSearchManager.
     * CSearchManager does not delete callback functions any more because
     * multiple search windows would not work with that.
     */
    _CCallback1<CDCMessage*> * m_pOurCallback;

    /** */
    //QHash<QString, DC_ListResult*> m_GroupHash;
    /** */
    //DC_ListResult * m_pEmptyGroup;
    /** Keep count of number of results not shown */
    int m_nFilteredResults;
    /** */
    SearchListModel *m_pSearchModel;
    /** */
    static QStringList *search_words;
    /** */
    static QStringHash download_dirs;

private slots:
    /** */
    void timerDone();
    /** */
    void slotSearchReturnPressed();
    /** */
    void slotAddSearchQueue();
    /** */
    void slotReset();
    /** */
    void slotDoubleClickedSearchResult(const QModelIndex &);
    /** */
    void slotRightButtonClickedSearchResult(const QPoint &);
    /** */
    /** context menu for the QHeaderView */
    void slotContextMenuHeader(const QPoint &);
    /** */
    void slotRefreshConnectedHubs();
    /** */
    void slotSearchSelected(int);
    /** */
    void slotPurgeHistory();
    /** */
    void slotSizeLimitChanged(int index);
    /** */
    void slotClickedHistory();
signals:
    void onDie(QWidget*);
};

inline void DCHubSearch::InitCompleterDict(){
    if (!search_words)
        search_words = new QStringList();
}

inline void DCHubSearch::DeInitCompleterDict(){
    if (search_words)
        delete search_words;

    search_words = NULL;
}

inline QStringList *DCHubSearch::GetCompleterDict(){
    return search_words;
}

inline DCHubSearch::QStringHash &DCHubSearch::GetDownloadDirs(){
    return download_dirs;
}

#endif
