/*
 * Copyright (C) 2009-2010  Lorenzo Bettini <http://www.lorenzobettini.it>
 * See COPYING file that comes with this distribution
 */

#ifndef SOURCEHIGHLIGHTIDE_H
#define SOURCEHIGHLIGHTIDE_H

#include <QMainWindow>
#include <QCloseEvent>
#include <QMutex>

#include <sstream>

#include <srchiliteqt/StyleComboBox.h>
#include <srchiliteqt/TextEditHighlighted.h>

#include "stepconditionvariable.h"

class QAction;
class QMenu;
class SourceHighlightIdeFrame;
class QFile;
class DebuggerThread;
class StatusBarFrame;
class QSettings;

namespace Ui
{
    class SourceHighlightIdeWindow;
}

namespace srchilite {
    class SourceHighlight;
    class HighlightEventListener;
    class HighlightEvent;
    class ParserException;
}

class FindReplaceDialog;

class SourceHighlightIde : public QMainWindow
{
      Q_OBJECT

public:
      SourceHighlightIde();
      ~SourceHighlightIde();

      /**
        * The method that does all the highlighting
        */
      void highlight();

      void readSettings(QSettings &settings);
      void writeSettings(QSettings &settings);

      QString userFriendlyCurrentFile();

      /**
        * Opens a lang definition file.
        * @param fileName
        */
      void openLangFile(const QString &fileName);

protected:
      void closeEvent(QCloseEvent *event);

      /**
        * Updates the contents of the output editor
        * @param contents the contents to update the editor
        * @param the output format
        */
      void updateHighlightedOutput(const QString &contents,
                                   const QString &outputFormat);

      /**
        * Updates the contents of the output editor, appending
        * the passed contents.
        * @param contents the contents to update the editor
        * @param the output format
        */
      void appendHighlightedOutput(const QString &contents,
                                   const QString &outputFormat);

protected slots:
      void highlightAll();

      void startDebug();
      void setDebugFileInfo(const QString &fileInfo, int line);
      void setDebugRegex(const QString &regex);
      void updateHighlighted();

      /**
        * Handles an exception message from source-highlight
        * @param ex the error message
        */
      void handleException(const QString &ex);

private slots:
      void newFile();
      void open();
      bool save();
      bool saveAs();
      bool saveHighlighted();
      bool saveHighlightedAs();
      void documentWasModified();

      void openInput();
      bool saveInput();
      bool saveInputAs();

      void currentStyleChanged(const QString &style);

      void debuggingFinished();
      void debuggingStarted();

      /**
        * highlight (the background) of the current line; this
        * has nothing to do with source highlighting.
        */
      void highlightCurrentLine();

      /**
        * Updates the info about the current line and column
        * (in the status bar)
        */
      void updateLineColInfo();

      void showFindReplaceDialog();

private:
      void createActions();
      void createToolBars();
      void createStatusBar();
      bool maybeSave();

      /**
        * Loads a lang definition file.
        * @param fileName
        */
      void loadFile(const QString &fileName);

      /**
        * Loads a file in the specified editor
        * @param fileName
        * @param editor
        */
      void loadFile(const QString &fileName, QTextEdit *editor);

      /**
        * Saves the contents of the specified editor into the
        * specified file.
        * @param fileName
        * @param editor
        */
      bool saveFile(const QString &fileName, const QTextEdit *editor);
      void setCurrentFile(const QString &fileName);

      /**
        * @param fullFileName
        * @return the file name without the path
        */
      QString strippedName(const QString &fullFileName);

      /**
        * @param fullFileName
        * @return the path without the file name
        */
      QString strippedPath(const QString &fullFileName);

      /**
        * Checks whether the lang file needs to be changed before
        * starting the highlighting.
        * @return whether the lang file was correctly saved
        */
      bool checkSaveBeforeHighlighting();

      /**
        * Changes the cursor position in the language
        * definition file editor (negative column means don't change
        * the column).
        * @param line
        * @param col
        */
      void setCursorPosition(int line, int col = -1);

      /**
        * Handles a parser exception from source-highlight
        * (e.g., go to the position in the editor where the error is)
        * @param pe the parser exception
        */
      void handleException(const srchilite::ParserException &pe);

      srchilite::SourceHighlight *createSourceHighlight();

      SourceHighlightIdeFrame *frame;

      StatusBarFrame *statusBarFrame;

      srchiliteqt::TextEditHighlighted *langTextEdit;
      QTextEdit *inputTextEdit;
      srchiliteqt::TextEditHighlighted *outputTextEdit;
      QString curFile;
      QString curInputFile;
      QString curHighlightedFile;
      QString curStyleFile;

      /// the lang file opened when we started debugging
      QString originalLangDefFile;

      DebuggerThread *debuggerThread;

      /*
      srchiliteqt::LanguageComboBox *languageComboBox;
      srchiliteqt::OutputFormatComboBox *outputFormatComboBox;
      srchiliteqt::StyleComboBox *styleComboBox;
    */

      /// whether the user customized the style with the color dialog
      bool styleModified;

      QMutex mutex;

      StepConditionVariable waitCondVariable;

      /// the buffer for output of the highlighting during debugging
      std::ostringstream debuggerHighlightedOutput;

private:
    Ui::SourceHighlightIdeWindow *ui;

    FindReplaceDialog *findReplaceDialog;
};

#endif
