#ifndef _KVI_IRCVIEW_H_
#define _KVI_IRCVIEW_H_
//=========================================================================================================
//
//   File : kvi_ircview.h
//   Creation date : Fri Mar 19 1999 05:39:01 by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//=========================================================================================================

#include "kvi_settings.h"
#include "kvi_string.h"
#include "kvi_wstring.h"
#include "kvi_list.h"

#include <qwidget.h>
#include <qframe.h>
#include <qlabel.h>
#include <qpixmap.h>      // needed
#include <qlistview.h>    // needed
#include <qtooltip.h>

class QScrollBar;
class QLineEdit;
class QFile;
class QCheckBox;
class QToolButton;
class QFontMetrics;

class KviWindow;
class KviFrame;
class KviConsole;


//=========================================================================================================
// Tip label widget
//=========================================================================================================


#ifdef _KVI_IRCVIEW_CPP_

	class KviIrcView;

	class KviIrcViewToolTip : public QToolTip
	{
	public:
		KviIrcViewToolTip(KviIrcView * pView);
		~KviIrcViewToolTip();
	protected:
		KviIrcView * m_pView;
	protected:
		virtual void maybeTip(const QPoint &pnt);
	public:
		void doTip(const QRect &rct,const QString &str){ tip(rct,str); };
	};
	
	//=========================================================================================================
	// Item for the filter list view
	//=========================================================================================================

	class KviIrcViewToolWidget;

	class KviIrcMessageCheckListItem : public QCheckListItem
	{
	public:
		KviIrcMessageCheckListItem(QListView * par,KviIrcViewToolWidget * w,int id);
		~KviIrcMessageCheckListItem();
	private:
		int m_iId;
		KviIrcViewToolWidget * m_pToolWidget;
	public:
		void setToolWidget(KviIrcViewToolWidget * w){ m_pToolWidget = w; };
		virtual void stateChange(bool bOn);
	};

	//=========================================================================================================
	// Search tools widget
	//=========================================================================================================

	class KviIrcView;

	class KviIrcViewToolWidget : public QFrame
	{
		friend class KviIrcView;
		Q_OBJECT
	protected:
		KviIrcViewToolWidget(KviIrcView * par);
		~KviIrcViewToolWidget();
	protected:
		KviIrcView * m_pIrcView;
		QLineEdit  * m_pStringToFind;
		QPoint       m_pressPoint;
	
		QCheckBox  * m_pCaseSensitive;
		QCheckBox  * m_pRegExp;
		QCheckBox  * m_pExtendedRegExp;
	
		QLabel     * m_pFindResult;
	
		QListView  * m_pFilterView;
	
		KviIrcMessageCheckListItem ** m_pFilterItems;
	
	public:
		void setFindResult(const QString & text);
		inline bool messageEnabled(int msg_type){ return m_pFilterItems[msg_type]->isOn(); }
		void forceRepaint();
	protected slots:
		void findPrev();
		void findNext();
		void filterEnableAll();
		void filterEnableNone();
		void filterSave();
		void filterLoad();
	protected:
		virtual void mouseMoveEvent(QMouseEvent *);
		virtual void mousePressEvent(QMouseEvent *);
	};
	

#else
	class KviIrcViewToolWidget;
	class KviIrcViewToolTip;
#endif




//=========================================================================================================
// Internal data structures
//=========================================================================================================
//
//#define KVI_IRCVIEW_MAX_TEXT_BLOCKS 64
//it is really enough...16 * 64 = 1 KB (maximum) for each text line
//

// Force this structure to be packed...
#ifdef COMPILE_ON_WINDOWS
	#pragma pack(push,old_packing,1)
	#define _KVI_PACKED
#else //!COMPILE_ON_WIDNOWS
	// this works only on gcc
	#ifdef __GNUC__
		#define _KVI_PACKED __attribute__((__packed__))
	#else
		#define _KVI_PACKED
	#endif
#endif //!COMPILE_ON_WINDOWS
typedef struct _KviIrcViewTextAttributeTag
{
	int            block_idx;                      //index in the data_ptr of the beginning of the block
	int            block_len;                      //length in chars of the block (excluding the terminator)
	unsigned char  attribute;          //attribute type
	union {
		unsigned short icon_id;        //KVI_TEXT_ICON attribute id
		struct {
			unsigned char  back;       //optional background color for KVI_TEXT_COLOR attribute
			unsigned char  fore;       //optional foreground color for KVI_TEXT_COLOR attribute (used also for KVI_TEXT_ESCAPE!!!)
		} _KVI_PACKED colors;
	} _KVI_PACKED attr_data;
	kvi_wchar_t   *escape_cmd;         //KVI_TEXT_ESCAPE attribute command buffer and KVI_TEXT_ICON icon name (non zeroed for other attributes!!!)
} _KVI_PACKED KviIrcViewTextAttribute;

typedef struct _KviIrcViewTextBlockTag
{
	int                      block_start;
	int                      block_len;            //length if the block in characters
	int                      block_width;          //width of the block in pixels
	KviIrcViewTextAttribute *attr_ptr;             //pointer to attributes or 0 for word wraps
} _KVI_PACKED KviIrcViewTextBlock;

typedef struct _KviIrcViewTextLine
{
	unsigned int             index;                //index of the text line (needed for find and splitting)

	QString                  data_str;

	int                      msg_type;

	int                      attr_len;             //number of allocated attr structures
	KviIrcViewTextAttribute *attr_ptr;             //pointer to the allocated structures
	// Precalculated text blocks
	int                      line_wraps;
	int                      max_line_width;       //width that the blocks were calculated for
	int                      num_text_blocks;      //number of allocated text blocks
	KviIrcViewTextBlock     *text_blocks_ptr;      //pointer to the allocated text blocks

	struct _KviIrcViewTextLine      *prev_line;
	struct _KviIrcViewTextLine      *next_line;
} _KVI_PACKED KviIrcViewTextLine;

#ifdef COMPILE_ON_WINDOWS
	#pragma pack(pop,old_packing)
#else //!COMPILE_ON_WINDOWS
	#undef _KVI_PACKED
#endif //!COMPILE_ON_WINDOWS

typedef struct _KviIrcViewTextBlockSelectionInfoTag
{
	int selection_type;
	int part_1_length;
	int part_1_width;
	int part_2_length;
	int part_2_width;
	int part_3_length;
	int part_3_width;
} KviIrcViewTextBlockSelectionInfo;

//=========================================================================================================
// Screen layout
//=========================================================================================================

//FIRST LINE (prev_line = 0) <---m_pFirstLine
//LINE
//--------------------SCREEN--
//LINE
//LINE
//LINE
//LINE <-------------------------m_pCurLine
//--------------------SCREEN--
//LAST LINE (next_line = 0) <----m_pLastLine

//=========================================================================================================
// The monster
//=========================================================================================================


class KVIRC_API KviIrcView : public QWidget
{
	friend class KviIrcViewToolTip;
	friend class KviIrcViewToolWidget;
	Q_OBJECT
	Q_PROPERTY(int TransparencyCapable READ dummyRead)
public:
	KviIrcView(QWidget *parent,KviFrame *pFrm,KviWindow *pWnd);
	~KviIrcView();
public:
	int dummyRead() const { return 0; };
private:
	KviIrcViewTextLine        * m_pFirstLine;
	KviIrcViewTextLine        * m_pCurLine;    // Bottom line in the view
	KviIrcViewTextLine        * m_pLastLine;
	KviIrcViewTextLine        * m_pCursorLine;

	// Highliting of links
	KviIrcViewTextBlock       * m_pLastLinkUnderMouse;
	int                         m_iLastLinkRectTop;
	int                         m_iLastLinkRectHeight;

	int                         m_iNumLines;
	int                         m_iMaxLines;

	unsigned int                m_uNextLineIndex;

	QPixmap                   * m_pPrivateBackgroundPixmap;
	QScrollBar                * m_pScrollBar;
	QToolButton               * m_pToolWidgetButton;

	KviIrcViewToolWidget      * m_pToolWidget;

	int                         m_iLastScrollBarValue;

	// Font related stuff (needs precalculation!)
	int                         m_iFontLineSpacing;
	int                         m_iFontLineWidth;
	int                         m_iFontDescent;
	int                         m_iFontCharacterWidth[256];    //1024 bytes fixed

	int                         m_iWrapMargin;
	int                         m_iMinimumPaintWidth;
	int                         m_iRelativePixmapY;
	int                         m_iIconWidth;
	int                         m_iIconSideSpacing;

	QPoint                      m_mousePressPos;
	QPoint                      m_mouseCurrentPos;

	// Selection
	int                         m_iSelectionBegin;
	int                         m_iSelectionTop;
	int                         m_iSelectionEnd;
	int                         m_iSelectionBottom;
	int                         m_iSelectionLeft;
	int                         m_iSelectionRight;

	bool                        m_bMouseIsDown;
	bool                        m_bShiftPressed;

	bool                        m_bSkipScrollBarRepaint;
	int                         m_iSelectTimer;
	//int                         m_iTipTimer;
	KviWStr                     m_szLastSelection;
	KviWStr                     m_szLastSelectionLine;
	KviWindow                 * m_pKviWindow;
	KviIrcViewTextBlockSelectionInfo m_TextBlockSelectionInfo;
	QFile                     * m_pLogFile;
	KviFrame                  * m_pFrm;
	bool                        m_bAcceptDrops;
	int                         m_iUnprocessedPaintEventRequests;
	bool                        m_bPostedPaintEventPending;
	KviPtrList<KviIrcViewTextLine> * m_pMessagesStoppedWhileSelecting;
	KviIrcView                * m_pMasterView;
	QFontMetrics              * m_pFm;
	
	KviIrcViewToolTip         * m_pToolTip;
public:
	void applyOptions();
	void enableDnd(bool bEnable);
	void appendText(int msg_type,const char *data_ptr,bool bRepaint=true);
	void appendText(int msg_type,const kvi_wchar_t *data_ptr,bool bRepaint=true);

	void removeHeadLine(bool bRepaint=false);
	void emptyBuffer(bool bRepaint=true);
	void getTextBuffer(QString &buffer);
	void setMaxBufferSize(int maxBufSize,bool bRepaint=true);
	int  maxBufferSize(){ return m_iMaxLines; }; //Never used ?
	bool saveBuffer(const char *filename);
	void findNext(const char * text,bool bCaseS = false,bool bRegExp = false,bool bExtended = false);
	void findPrev(const char * text,bool bCaseS = false,bool bRegExp = false,bool bExtended = false);
	KviWindow * parentKviWindow(){ return m_pKviWindow; };
	KviConsole * console();
	// A null pixmap passed here unsets the private backgrdound.
	void setPrivateBackgroundPixmap(const QPixmap &pixmap,bool bRepaint=true);
	bool hasPrivateBackgroundPixmap(){ return (m_pPrivateBackgroundPixmap != 0); };

	//==============================================================================================
	// Logging
	// Stops previous logging session too...
	bool startLogging(const char *filename,bool bPrependCurBuffer = false);
	void stopLogging();
	bool isLogging(){ return (m_pLogFile != 0); };
	void getLogFileName(KviStr &buffer);
	void add2Log(const char *buffer,int buf_len=-1);
	void add2Log(const QString &szBuffer);
	void flushLog();

	//==============================================================================================
	// Channel view splitting
	void setMasterView(KviIrcView * v);
	void splitMessagesTo(KviIrcView * v);
	void joinMessagesFrom(KviIrcView * v);

	void prevLine();
	void nextLine();
	void nextPage();
	void prevPage();
	virtual QSize sizeHint() const;
	const QString & lastLineOfText();
public slots:
	void clearBuffer();
	void toggleToolWidget();
  //  void inputWidgetKeyPressed();
signals:
	void rightClicked();
	void dndEntered();
	void fileDropped(const char *);
private:
	void setCursorLine(KviIrcViewTextLine * l);
	KviIrcViewTextLine * getVisibleLineAt(int xPos,int yPos);
	void getLinkEscapeCommand(KviStr &buffer,const char * escape_cmd,const char * escape_label,int label_len);
	void resizeMemBuffer();
	void appendLine(KviIrcViewTextLine *ptr,bool bRepaint);
	void postUpdateEvent();
	void fastScroll(int lines = 1);
	const kvi_wchar_t * getTextLine(int msg_type,const kvi_wchar_t * data_ptr,KviIrcViewTextLine *line_ptr);
	void calculateLineWraps(KviIrcViewTextLine *ptr,int maxWidth);
	void recalcFontVariables(const QFont &font);
	bool checkSelectionBlock(KviIrcViewTextLine * line,int left,int bottom,int bufIndex);
	void calculateSelectionBounds();
	KviIrcViewTextBlock * getLinkUnderMouse(int xPos,int yPos,QRect * pRect = 0,KviWStr * linkCmd = 0,KviWStr * linkText = 0);
	//void abortTip();
	void doLinkToolTip(const QRect &rct,KviStr &linkCmd,KviStr &linkText);
protected:
	virtual void paintEvent(QPaintEvent *);
	virtual void resizeEvent(QResizeEvent *);
	virtual void mousePressEvent(QMouseEvent *e);
	virtual void mouseReleaseEvent(QMouseEvent *);
	virtual void mouseDoubleClickEvent(QMouseEvent *e);
	virtual void mouseMoveEvent(QMouseEvent *e);
	virtual void timerEvent(QTimerEvent *e);
	virtual void dragEnterEvent(QDragEnterEvent *e);
	virtual void dropEvent(QDropEvent *e);
	virtual bool event(QEvent *e);
	virtual void wheelEvent(QWheelEvent *e);
	void maybeTip(const QPoint &pnt);
protected slots:
	virtual void scrollBarPositionChanged(int newValue);
	void masterDead();
};

#endif //_KVI_IRCVIEW_H_
