/* Copyright (C) 2002 Mickael Marchand <marchand@kde.org>  -*-c++-*-

	 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.

	 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; see the file COPYING.  If not, write to
	 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
	 Boston, MA 02111-1307, USA.
	 */


#ifndef VIMDOCUMENT_H
#define VIMDOCUMENT_H

#include <kparts/part.h>
#include <ktexteditor/view.h>
#include <ktexteditor/editor.h>
#include <ktexteditor/document.h>
#include <ktexteditor/editinterface.h>
#include <ktexteditor/undointerface.h>
#include <ktexteditor/cursorinterface.h>
#include <ktexteditor/selectioninterface.h>
#include <ktexteditor/highlightinginterface.h>
#include <ktexteditor/searchinterface.h>
#include <ktexteditor/markinterface.h>
#include <ktexteditor/wordwrapinterface.h>
#include <ktexteditor/encodinginterface.h>
#include <qptrlist.h>
#include "vimpartbrowserextension.h"
#include "vimwidget.h"
#include "vimdcop.h"

class VimWidget;
class VimDCOP;

namespace Vim {

	class View;
	class Cursor;

	class Document : 
		public KTextEditor::Document,
		public KTextEditor::EditInterface,
		public KTextEditor::CursorInterface,
		public KTextEditor::UndoInterface,
		public KTextEditor::SelectionInterface,
		//public KTextEditor::HighlightingInterface // not a good idea, seems really useless here
		public KTextEditor::SearchInterface,
		//public KTextEditor::MarkInterface,
		public KTextEditor::WordWrapInterface,
		public KTextEditor::EncodingInterface
	{
		Q_OBJECT

		public:
			Document(bool bReadOnly=false, bool bSingleView=false, bool bWantBrowser=false, QWidget *parentWidget = 0, const char *widgetName = 0,QObject *parent = 0, const char *name = 0);
			virtual ~Document();

			void addView (KTextEditor::View *view);
			void removeView (KTextEditor::View *view);

			virtual void setReadWrite ( bool rw );
			virtual bool isReadWrite ( );

			bool m_singleView, m_readOnly,m_browserView;
			bool closeURL();
			QString getServerName() { return activeWidget() ? activeWidget()->serverName() : QString::null; }

		protected:
			virtual bool openFile();
			virtual bool saveFile();
			VimWidget* activeWidget() const;

		public slots:
			//these are the events receiver from DCOP signals
			void keyboardEvent(QCString,int,int);
			void mousePEvent(int,int,int,int);
			void mouseWhlEvent(int,int,int,int);
			void mouseDblClickEvent(int,int,int,int);

		private:
			KTextEditor::View *activeView;
			VimpartBrowserExt *browser;
			VimDCOP *receiver;

		signals: //kate compatibility, kwrite integration until a proper fix
			void fileNameChanged();

			// -- Document ---------------------------------------------------------------
		public:
			/**
			 * Create a view that will display the document data. You can create as many
			 * views as you like. When the user modifies data in one view then all other
			 * views will be updated as well.
			 */
			KTextEditor::View *createView ( QWidget *parent, const char *name = 0 );

			/*
			 * Accessor to the list of views.
			 */
			QPtrList<KTextEditor::View> views () const;

		private:
			QPtrList<KTextEditor::View> _views;


		public:
			void copy();
			
			// -- EditInterface ------------------------------------------------------
		public:
			/**
			 * @return the complete document as a single QString
			 */
			QString text () const;    
			/**
			 * @return a QString
			 */
			QString text ( unsigned int startLine, unsigned int startCol, unsigned int endLine, unsigned int endCol ) const;

			/**
			 * @return All the text from the requested line.
			 */
			QString textLine ( unsigned int line ) const;

			/**
			 * @return The current number of lines in the document
			 */
			unsigned int numLines () const;

			/**
			 * @return the number of characters in the document
			 */
			unsigned int length () const;

			/**
			 * @return the number of characters in the line (-1 if no line "line")
			 */
			int lineLength ( unsigned int line ) const;

			/**
			 * Set the given text into the view.
			 * Warning: This will overwrite any data currently held in this view.
			 */
			bool setText ( const QString &text );

			/**
			 *  clears the document
			 * Warning: This will overwrite any data currently held in this view.
			 */
			bool clear ();

			/**
			 *  Inserts text at line "line", column "col"
			 *  returns true if success
			 */
			bool insertText ( unsigned int line, unsigned int col, const QString &text );

			/**
			 *  remove text at line "line", column "col"
			 *  returns true if success
			 */
			bool removeText ( unsigned int startLine, unsigned int startCol, unsigned int endLine, unsigned int endCol );

			/**
			 * Insert line(s) at the given line number. If the line number is -1
			 * (the default) then the line is added to end of the document
			 */
			bool insertLine ( unsigned int line, const QString &text );

			/**
			 * Insert line(s) at the given line number. If the line number is -1
			 * (the default) then the line is added to end of the document
			 */
			bool removeLine ( unsigned int line );

		signals:
			void textChanged ();
			void charactersInteractivelyInserted(int ,int ,const QString&);


			// -- UndoInterface -----------------------------------------------------------------------------
		public:
			void clearUndo ();
			void clearRedo ();
			unsigned int undoCount () const;
			unsigned int redoCount () const;
			unsigned int undoSteps () const;
			void setUndoSteps ( unsigned int steps );

		public slots:
			void undo ();
			void redo ();

		signals: //signals are a big problem with vim
			void undoChanged ();


			// -- CursorInterface  --------------------------------------------------------------------------
		public:
			/**
			 * Create a new cursor object
			 */
			KTextEditor::Cursor *createCursor ( );

			/*
			 * Accessor to the list of views.
			 */
			QPtrList<KTextEditor::Cursor> cursors () const {
				return _cursors;
			}

			friend class Cursor;
		private:
			QPtrList<KTextEditor::Cursor> _cursors;


			// -- SelectionInterface ----------------------------------------------------------------------
		public:
			/**
			 *  @return set the selection from line_start,col_start to line_end,col_end
			 */
			bool setSelection ( unsigned int startLine, unsigned int startCol, unsigned int endLine, unsigned int endCol );

			/**
			 *  removes the current Selection (not Text)
			 */
			bool clearSelection ();

			/**
			 *  @return true if there is a selection
			 */
			bool hasSelection () const;

			/**
			 *  @return a QString for the selected text
			 */
			QString selection () const;

			/**
			 *  removes the selected Text
			 */
			bool removeSelectedText ();

		public slots:
			/**
			 *  select the whole text
			 */
			bool selectAll();

		signals: // again Signals in vim are hard to generate ...
			void selectionChanged ();


			// -- HighlightingInterface ---------------------------------------------------------------------
		public:
			/**
			 * returns the current active highlighting mode
			 */
			unsigned int hlMode ();

			/**
			 * set the current active highlighting mode
			 */
			bool setHlMode (unsigned int mode);

			/**
			 * returns the number of available highlightings
			 */
			unsigned int hlModeCount ();

			/**
			 * returns the name of the highlighting with number "mode"
			 */
			QString hlModeName (unsigned int mode);

			/**
			 * returns the sectionname of the highlighting with number "mode"
			 */
			QString hlModeSectionName (unsigned int mode);

		signals:
			void hlChanged ();
			
			// -- SearchInterface ----------------------------------------------------------------------
		public:
			bool searchText (unsigned int startLine, unsigned int startCol,
					const QString &text, unsigned int *foundAtLine, unsigned int *foundAtCol,
					unsigned int *matchLen, bool casesensitive = true, bool backwards = false);

			bool searchText (unsigned int startLine, unsigned int startCol,
					const QRegExp &regexp, unsigned int *foundAtLine,
					unsigned int *foundAtCol, unsigned int *matchLen, bool backwards = false);

			
			// -- MarkInterface ------------------------------------------------------------------------
			// public:
			//     uint mark (uint line);

			//     void setMark (uint line, uint markType);
			//     void clearMark (uint line);

			//     void addMark (uint line, uint markType);
			//     void removeMark (uint line, uint markType);

			//     QPtrList<KTextEditor::Mark> marks ();
			//     void clearMarks ();

			// signals:
			//     void marksChanged();


			// -- WordWrapInterface ------------------------------------------------------------------------
		public:
			void setWordWrap (bool);
			bool wordWrap ();

			void setWordWrapAt (unsigned int );
			unsigned int wordWrapAt ();

			// -- EncodingInterface ------------------------------------------------------------------------
		public:
			void setEncoding (const class QString &e);
			QString encoding() const;
	};
}

#endif // VIMDOCUMENT_H
