/*
	QAD - Qt ADvanced

	Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 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 Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef QCODEEDIT_H
#define QCODEEDIT_H

#include <QPlainTextEdit>
#include <QTreeWidget>
#include <QScrollBar>
#include "iconedlabel.h"


namespace Ui {
	class QCodeEdit;
}


class QAD_EXPORT QCodeEdit: public QWidget
{
	Q_OBJECT
	Q_PROPERTY(QString text READ text WRITE setText)
	Q_PROPERTY(bool showSpaces READ showSpaces WRITE setShowSpaces)
	Q_PROPERTY(bool showLineNumbers READ showLineNumbers WRITE setShowLineNumbers)
	Q_PROPERTY(QFont editorFont READ editorFont WRITE setEditorFont)
	
public:
	QCodeEdit(QWidget * parent = 0);
	~QCodeEdit();
	
	enum ACClassType {
		Keyword,
		Function,
		Namespace
	};
	
	QTextCursor textCursor() const;
	QTextDocument * document() const;
	void setDocument(QTextDocument * doc);
	void setTextCursor(const QTextCursor & c);
	void centerCursor();
	void insertText(const QString & text);
	void appendText(const QString & text);
	void setCustomExtraSelection(const QList<QTextEdit::ExtraSelection> & es);
	QRect cursorRect() const;
	QRect cursorRect(const QTextCursor & cursor) const;
	QString text() const;
	QStringList cursorScope() const;
	bool showSpaces() const {return spaces_;}
	bool showLineNumbers() const;

	void setEditorFont(QFont f);
	QFont editorFont() const;
	
	QPlainTextEdit * textEdit() const;
	
	void registerAutoCompletitionClass(int id, ACClassType ac_class, const QString & name, const QIcon & icon = QIcon()) {ac_classes[id] = ACClass(id, ac_class, name, icon);}
	
protected:
	typedef QPair<QString, QString> StringsPair;
	typedef QPair<int, QList<StringsPair> > ACPair;
	typedef QList<ACPair> ACList;
	
	virtual ACList autoCompletitionList(const QStringList & scope, const QString & written) const {return ACList();}
	virtual void parse() {}
	virtual void documentUnset() {}
	virtual void documentChanged(QTextDocument * d) {}
	QString selectArg(QString s, int arg);
	void raiseHelp(QTextCursor tc, int arg = -1);
	QTextCursor functionStart(QTextCursor tc, int * arg);
	ACList wordsCompletitionList(const QString & written) const;
	QPair<QStringList, QString> getScope(QTextCursor tc, bool * ok = 0);
	static int skipRange(const QString & s, int pos, QChar oc, QChar cc, QChar sc = QChar());
	static int skipCWord(const QString & s, int pos);
	static bool matchWritten(QString s, QString w);
	static QChar pairChar(QChar c);
	
	Ui::QCodeEdit * ui;

private:
	struct ACClass {
		ACClass(int i = -2, ACClassType c = QCodeEdit::Keyword, const QString & n = QString(), const QIcon & ic = QIcon()): id(i), class_(c), name(n), icon(ic) {}
		int id;
		ACClassType class_;
		QString name;
		QIcon icon;
	};
	
	QTreeWidget * completer;
	IconedLabel * lbl_help[2];
	QFrame * widget_help;
	QTextEdit::ExtraSelection es_line, es_cursor, es_bracket, es_range, es_search;
	QList<QTextEdit::ExtraSelection> es_selected, es_custom, es_brackets, es_search_list;
	QMap<int, ACClass> ac_classes;
	QStringList cursor_scope;
	int prev_lc, auto_comp_pl, timer, cur_search_ind, pos_press, pos_el_press;
	bool spaces_, _ignore_focus_out, _first, _destructor, _replacing;
	
	bool eventFilter(QObject * o, QEvent * e);
	void showEvent(QShowEvent * );
	void timerEvent(QTimerEvent * );
	void leaveEvent(QEvent * );
	void changeEvent(QEvent * e);
	void highlightBrackets();
	void applyExtraSelection();
	void nextCompletition();
	void previousCompletition();
	void clearSearch();
	void moveToSearch();
	int searchIndFromCursor();
	
private slots:
	void syncScrolls();
	void scrollUp();
	void scrollDown();
	void hideHelp();
	void deleteLine();
	void copyLineUp();
	void copyLineDown();
	void moveLineUp();
	void moveLineDown();
	void indent();
	void deindent();
	void autoIndent();
	void invokeAutoCompletition(bool force = false);
	void commitCompletition();
	void searchAll();
	void search_triggered();
	void textEdit_cursorPositionChanged();
	void textEdit_textChanged();
	void textEdit_selectionChanged();
	void on_comboSearch_currentTextChanged(const QString & t);
	void on_buttonReplace_clicked();
	void on_buttonReplaceSearch_clicked();
	void on_buttonReplaceAll_clicked();

public slots:
	void updateLines();
	void scrollToTop();
	void newLine();
	void newLineBefore();
	void setFocus();
	void setText(const QString & t);
	void setShowSpaces(bool yes);
	void setShowLineNumbers(bool yes);
	void search(const QString & t);
	void searchNext(bool next = true);
	void searchPrevious();
	void hideSearch();
	
signals:
	void textChanged();
	void parseRequest();
	
};


#endif // QCODEEDIT_H
