/***************************************************************************
 *   Copyright (C) 2007-2011 by Peter Semiletov                            *
 *   peter.semiletov@gmail.com                                             *
 *                                                                         *
 *   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 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 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.             *
 ***************************************************************************/

/*
** Copyright (C) 2006-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
*/
/*
Diego Iastrubni <elcuco@kde.org> //some GPL'ed code from new-editor-diego-3, found on qtcentre forum
*/

/*
code from qwriter:
 *   Copyright (C) 2009 by Gancov Kostya                                   *
 *   kossne@mail.ru                                                        *
*/


#ifndef DOCUMENT_H
#define DOCUMENT_H

#include <QtGui>

#include "logmemo.h"
#include "tio.h"

#include "todo.h"



class LineNumberArea;
class document_holder;
class CDocument;



class CTEAEdit: public QPlainTextEdit
{
  Q_OBJECT

private:
    
  QString indent_val;  
  QList <QTextEdit::ExtraSelection> extraSelections;
  QTextEdit::ExtraSelection selection;

public:

  CDocument *doc;

  QColor currentLineColor;
  QColor brackets_color;
  QColor margin_color;
  QColor linenums_bg;
  QColor text_color;

  QWidget *lineNumberArea;

  bool highlightCurrentLine;
  bool hl_brackets;
  bool draw_margin;
  bool draw_linenums;
  
  bool use_hl_wrap;

  bool auto_indent;
  bool spaces_instead_of_tabs;
  int tab_sp_width; //in spaces
  int brace_width; //in pixels
  int margin_pos; //in chars
  int margin_x; //in pixels


  CTEAEdit (QWidget *parent = 0);
  //~CTEAEdit();

  void setCurrentLineColor (const QColor &newColor);
  void set_brackets_color (const QColor &newColor);
  void set_show_linenums (bool enable);
  void set_show_margin (bool enable);
  void set_margin_pos (int mp);
  void set_hl_cur_line (bool enable);
  void set_hl_brackets (bool enable);

  void indent();
  void un_indent();
  void calc_auto_indent();
  void setup_brace_width();

  void braceHighlight();
  
  void lineNumberAreaPaintEvent(QPaintEvent *event);
  int lineNumberAreaWidth();

protected:

//  void dragEnterEvent (QDragEnterEvent *event);
//  void dropEvent (QDropEvent *event);

  bool canInsertFromMimeData (const QMimeData *source);
  void insertFromMimeData (const QMimeData *source);

  void paintEvent(QPaintEvent *event);
  void keyPressEvent (QKeyEvent *event);    
  void resizeEvent(QResizeEvent *event);

private slots:

  void updateLineNumberAreaWidth (int newBlockCount);
  void cb_cursorPositionChanged();
  void updateLineNumberArea (const QRect &, int);
};


class CSyntaxHighlighter: public QSyntaxHighlighter
{
  Q_OBJECT

protected:

  void highlightBlock (const QString &text);

public:

  struct HighlightingRule
        {
         QRegExp pattern;
         QTextCharFormat format;
        };


  CDocument *document;
  bool casecare;
  bool wrap;
  
  QString exts;
  QString langs;
    
  QString cm_mult;
  QString cm_single;
    
  CSyntaxHighlighter (QTextDocument *parent = 0, CDocument *doc = 0);

  QVector <HighlightingRule> highlightingRules;

  QTextCharFormat singleLineCommentFormat;
  QTextCharFormat multiLineCommentFormat;

  QRegExp commentStartExpression;
  QRegExp commentEndExpression;

  void load_from_xml (const QString &fname);
};


class CDocument: public QObject
{
  Q_OBJECT

public:

 // Q_PROPERTY(QString selected_text READ get_selected_text WRITE set_selected_text)
  //Q_PROPERTY(QString all_text READ get_all_text WRITE set_all_text)
  //Q_PROPERTY(bool has_selection READ get_has_selection)

  bool cursor_xy_visible;
  bool eol_changed;

  QHash <QString, QString> fnameswoexts;
  
  QString new_eol;
  QString def_eol;
  
  document_holder *holder;
  CSyntaxHighlighter *highlighter;
  CTEAEdit *textEdit;

  QStringList labels;

  QString markup_mode;
  QString file_name;
  QString text_to_search;
  QString charset;
  QWidget *tab_page;
  int position;

  CDocument (QObject *parent = 0);
  ~CDocument();

  QString get_selected_text() const;
  void set_selected_text (const QString &value);

  /*
  void set_all_text (const QString &value);
  QString get_all_text() const;
  bool get_has_selection() const;
  */
  void create_new();
  void set_tab_caption (const QString &fileName);
  bool save_with_name (const QString &fileName, const QString &codec);
  bool save_with_name_plain (const QString &fileName);
  void goto_pos (int pos);
  QString get_filename_at_cursor();
  QStringList get_words();
  void set_hl (bool mode_auto = true, const QString &theext = "txt");
  bool open_file (const QString &fileName, const QString &codec);
  void insert_image (const QString &full_path);
  void set_markup_mode();
  void reload (const QString &enc);
  int get_tab_idx();
  QString get_triplex();
  void update_status();
  void update_title (bool fullname = TRUE);

  void update_labels();
};


class document_holder: public QObject
{
  Q_OBJECT

public:

  CTioHandler tio_handler;

  QString fname_current_session;

  QHash <QString, QString> palette;
  QHash <QString, QString> hls;

  QLabel *l_status_bar;
  QString dir_config;

  QString fname_crapbook;

  CTodo todo;


  QString markup_mode;
  QStatusBar *status_bar;
  CLogMemo *log;
  QList <CDocument*> list;
  QMainWindow *parent_wnd;
  QTabWidget *tab_widget;
//  QSettings *settings;

  QMenu *recent_menu;
  QStringList recent_files;
  QString recent_list_fname;

  ~document_holder();

  CDocument* create_new();
  CDocument* open_file (const QString &fileName, const QString &codec);
  CDocument* open_file_triplex (const QString &triplex);
  void reload_recent_list();

  void save_to_session (const QString &fileName);
  void load_from_session (const QString &fileName);
  void load_palette (const QString &fileName);

  void close_by_idx (int i);
  void close_current();
  void apply_settings();
  void apply_settings_single (CDocument *d);

  void add_to_recent (CDocument *d);
  void update_recent_menu();

  CDocument* get_current();

  public slots:

  void open_recent();
};


class LineNumberArea: public QWidget
{
public:

    CTEAEdit *codeEditor;

    LineNumberArea (CTEAEdit *editor = 0) : QWidget (editor) {
        codeEditor = editor;
    }

    QSize sizeHint() const {
        return QSize(codeEditor->lineNumberAreaWidth(), 0);
    }

protected:
    void paintEvent(QPaintEvent *event) {
        codeEditor->lineNumberAreaPaintEvent(event);
    }

};


#endif
