/***************************************************************************
                          document.h  -  description
                             -------------------
    begin                : Tue Jun 6 2000
    copyright            : (C) 2000 by Dmitry Poplavsky & Alexander Yakovlev & Eric Laffoon <pdima@users.sourceforge.net,yshurik@penguinpowered.com,sequitur@easystreet.com>
                           (C) 2001-2004 Andras Mantia <amantia@kde.org>
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef DOCUMENT_H
#define DOCUMENT_H

//qt includes
#include <tqdatetime.h>
#include <tqdict.h>
#include <tqmap.h>
#include <tqwidget.h>

#include <kurl.h>
#include <ktexteditor/markinterfaceextension.h>

//own includes
#include "qtag.h"

/**
  *@author Dmitry Poplavsky & Alexander Yakovlev & Eric Laffoon & Andras Mantia
  */

class TQDomDocument;
class TQEvent;
class TQFocusEvent;
class TQTextCodec;
class TQStringList;
class KConfig;
class KTempFile;
class KURL;
class Tag;
class Node;
class Project;
class undoRedo;
struct AreaStruct;
struct DTDStruct;

namespace KTextEditor
{
  class CodeCompletionInterface;
  class CompletionEntry;
  class ConfigInterface;
  class Document;
  class EditInterface;
  class EditInterfaceExt;
  class EncodingInterface;
  class MarkInterface;
  class SelectionInterface;
  class SelectionInterfaceExt;
  class View;
  class ViewCursorInterface;
  class Mark;
}

class Document : public TQWidget{
   Q_OBJECT
  

public:
  Document(KTextEditor::Document *doc,
           TQWidget *parent = 0, const char *name = 0, WFlags f=0);
  ~Document();

  KURL url();

  bool isUntitled();
  void setUntitledUrl(const TQString &url);
  /** Returns tag name at specified position */
  TQString getTagNameAt(int line, int col );

  void selectText(int x1, int y1, int x2, int y2 );
  void replaceSelected(const TQString &s);

  /** insert tag in document  */
  void insertTag(const TQString &s1, const TQString &s2 = TQString());
  /** Change the current tag's attributes with those from dict */
  void changeTag(Tag *tag, TQDict<TQString> *dict );
  /**Change the attr value of the called attrName to attrValue*/
  void changeTagAttribute(Tag *tag, const TQString& attrName, const TQString&attrValue);
  /**Change the namespace in a tag. Add if it's not present, or remove if the
  namespace argument is empty*/
  void changeTagNamespace(Tag *tag, const TQString& nameSpace);
  /** Insert the content of the url into the document. */
  void insertFile(const KURL& url);
  /** Inserts text at the current cursor position */
  void insertText(const TQString &text, bool adjustCursor = true, bool reparse = true);
  /** Recursively insert the mandatory childs of tag. Returns true if a child was
  inserted.*/
  bool insertChildTags(TQTag *tag, TQTag* lastTag = 0L);

  TQPoint getGlobalCursorPos();
  TQString find(const TQRegExp& rx, int sLine, int sCol, int& fbLine, int&fbCol, int &feLine, int&feCol);
  TQString findRev(const TQRegExp& rx, int sLine, int sCol, int& fbLine, int&fbCol, int &feLine, int&feCol);
  /** Get the view of the document */
  KTextEditor::View* view();
  /** Get the KTextEditor::Document of the document */
  KTextEditor::Document* doc();
  /** Sets the modifiedFlag value. */
  void setModified(bool flag);
  /** Returns true if the document was modified. */
  bool isModified();

  /** Creates a temporary file where the editor content is saved.
  */
  void createTempFile();
  /** Closes and removes the temporary file. */
  void closeTempFile();
  /** Returns the name of the temporary file, TQString() if no temporary file exists. */
  TQString tempFileName();

  /** Returns the DTD identifier for the document */
  TQString getDTDIdentifier();
  /** Sets the DTD identifier */
  void setDTDIdentifier(const TQString &id);
  /** Get a pointer to the current active DTD. If fallback is true, this always gives back a valid and known DTD pointer: the active, the document specified and in last case the application default document type. */
  const DTDStruct* currentDTD(bool fallback = true);
  /** Get a pointer to the default DTD (document, or app). */
  const DTDStruct* defaultDTD() const;
  /** Find the DTD name for a part of the document. */
  TQString findDTDName(Tag **tag);
  /** Retrives the text from the specified rectangle. The KTextEditor::EditInterface::text seems to not
work correctly. */
  TQString text(int bLine, int bCol, int eLine, int eCol) const;
  /** Same as the above, but using AreaStruct as an argument */
  TQString text(const AreaStruct &area) const;
  /** Code completion was requested by the user. */
  void codeCompletionRequested();
  /** Bring up the code completion tooltip. */
  void codeCompletionHintRequested();
  /** Returns the dirty status. */
  bool dirty() const {return m_dirty;};
  void setDirtyStatus(bool status) {m_dirty = status;};
  /** Ask for user confirmation if the file was changed outside. */
  void checkDirtyStatus();
  /** Save the document and reset the dirty status. */
  void save();
  /** Save the document under a new name and calculate the new md5sum. */
  bool saveAs(const KURL& url);
  /** Enable or disable the visibility of groups for a DTEP.*/
  void enableGroupsForDTEP(const TQString& dtepName, bool enable = true);
  /** Clears the selected DTEP list */
  void resetGroupsForDTEPList();
  /** Find the word until the first word boundary backwards */
  TQString findWordRev(const TQString& textToSearch, const DTDStruct *dtd = 0L);
  /** Returns the changed status since the last query. Resets changed.*/
  bool hasChanged();
  /** Sets the changed status.*/
  void setChanged(bool newStatus);
  /** Paste the contents of clipboard into the document */
  void paste();

  /** disable/enable the parser*/
  void activateParser(bool activation) {reparseEnabled = activation;}
  bool parserActivated() {return reparseEnabled;}

  /** returns all the areas that are between tag and it's closing pair */
  TQStringList tagAreas(const TQString &tag, bool includeCoordinates, bool skipFoundContent);

  /** disable/enable the repaint of the Kate view */
  void activateRepaintView(bool activation);
  bool RepaintViewActivated() {return repaintEnabled;}

  void setErrorMark(int line);
  void clearErrorMarks();
  void convertCase();

  /** returns the word under the cursor */
  TQString currentWord();
  /** Opens the url. The url must be valid and the file pointed to it must exists. */
  void open(const KURL &url, const TQString &encoding);
  /**
   * Opens a file in the editor part.
   * @param url
   */
  bool openURL(const KURL& url);
  /** Reads the DTD info from the file, tries to find the correct DTD and builds the tag/attribute list from the DTD file. */
  void processDTD(const TQString& documentType = TQString());

  /** Resets the list of DTEPs found in the document */
  void resetDTEPs();
  /** Adds a DTEP to the list of DTEPs present in the document */
  void addDTEP(const TQString &dtepName);
  /** Returns the list of DTEPs that should appear in the structure tree. By default
      this is the list of DTEPs present in the document, but the user can turn on/
      off them with the help of RMB->Show Groups For in the structure tree */
  TQStringList groupsForDTEPs();

  bool busy;

  KTextEditor::ViewCursorInterface *viewCursorIf;
  KTextEditor::SelectionInterface *selectionIf;
  KTextEditor::SelectionInterfaceExt *selectionIfExt;
  KTextEditor::EditInterface *editIf;
  KTextEditor::EncodingInterface *encodingIf;
  KTextEditor::EditInterfaceExt *editIfExt;
  KTextEditor::CodeCompletionInterface *codeCompletionIf;
  KTextEditor::ConfigInterface* configIf;
  KTextEditor::MarkInterface* markIf;

  /** Hold the list of user tags (real or not, like functions) that are in the document*/
  TQTagList userTagList;
  /** The undo/redo stack */
  undoRedo *docUndoRedo;

  bool isBackedUp();
  /** Creates an automatic backup copy for the crash recovering mechanism */
  void createBackup(KConfig* config);
  /** No descriptions */
  TQString backupPathEntryValue();
  /** No descriptions */
  void setBackupPathEntryValue(const TQString& ev);
  /** Removes automatic backup copies */
  void removeBackup(KConfig *config);
  /** create a string using document path string */
  static TQString hashFilePath(const TQString& p);
  TQString annotationText(uint line);
  void setAnnotationText(uint line, const TQString& text);
  TQMap<uint, TQPair<TQString, TQString> > annotations() {return m_annotations;}
  void addAnnotation(uint line, const TQPair<TQString, TQString>& annotation);
  void clearAnnotations();

public slots:

  /** Called after a completion is inserted */
  void slotCompletionDone( KTextEditor::CompletionEntry completion );
  /** Called when a user selects a completion, we then can modify it */
  void slotFilterCompletion(KTextEditor::CompletionEntry*,TQString *);
  /** Called whenever a user inputs text */
  void slotCharactersInserted(int ,int ,const TQString&);
  /** Called when the code completion is aborted.*/
  void slotCompletionAborted();
  /** Called whenever the text in the document is changed. */
  void slotTextChanged();
  /** Handle the text changed events. Usually called from slotTextChanged,
  but it's possible to force the handling by calling manually and setting
  forced to true. */
  void slotDelayedTextChanged(bool forced = false);
  void slotDelayedScriptAutoCompletion();
  void slotDelayedShowCodeCompletion();

signals:
 /** Emitted when the internal text editor got the focus */
  void editorGotFocus();
  void openingFailed(const KURL &url);
  void openingCompleted(const KURL &url);

  void breakpointMarked(Document*, int);
  void breakpointUnmarked(Document*, int);
  void showAnnotation(uint, const TQString&, const TQPair<TQString, TQString>&);

private slots:
  void slotReplaceChar();
  void slotOpeningCompleted();
  void slotOpeningFailed(const TQString &errorMessage);
  /** Called when a file on the disk has changed. */
  void slotFileDirty(const TQString& fileName);

  void slotMarkChanged(KTextEditor::Mark mark, KTextEditor::MarkInterfaceExtension::MarkChangeAction action);
private:
  /**
   * Finds the beginning of a tag in the document, starting from a position.
   * @param position start to look from this position backwards
   * @return the position of the starting character or an empty TQPoint if not found
   */
  TQPoint findTagBeginning(const TQPoint& position);
  TQPoint findTagEnd(const TQPoint& position);



  TQMap<uint, TQPair<TQString, TQString> > m_annotations;
  TQString untitledUrl;
  int m_replaceLine;
  int m_replaceCol;
  TQString m_replaceStr;

  KTextEditor::Document *m_doc;
  KTextEditor::View *m_view;

  KTempFile *tempFile;
  TQString m_tempFileName;
  TQDateTime m_modifTime;
  /* path of the backup copy file of the document */
  TQString m_backupPathValue;
  TQString dtdName;
  TQString m_encoding;
  TQTextCodec *m_codec;
/*The DTD valid in the place where the completion was invoked.*/
  const DTDStruct *completionDTD;

  bool changed;
  bool completionInProgress;
  bool completionRequested; ///< true if the code completion was explicitely requested by the user
  bool argHintVisible;
  bool hintRequested;
  bool reparseEnabled;
  bool repaintEnabled;
  bool delayedTextChangedEnabled;
  /** True if the document is dirty (has been modified outside). */
  bool m_dirty;
  TQString m_md5sum;
  Project *m_project;
  /** Parse the document according to this DTD. */
  TQStringList m_groupsForDTEPs; ///< The list of the DTEPs for which the groups should appear in the structure tree
  TQStringList m_DTEPList; ///< The list of all DTEPs found in the document
  //stores the data after an autocompletion. Used when bringing up the
  //autocompletion box delayed with the singleshot timer (workaround for
  //a bug: the box is not showing up if it is called from slotCompletionDone)
  int m_lastLine, m_lastCol;
  TQValueList<KTextEditor::CompletionEntry>* m_lastCompletionList;

  /** Get list of possibile variable name completions */
  TQValueList<KTextEditor::CompletionEntry>* getGroupCompletions(Node *node, const StructTreeGroup& groupName, int line, int col);
  /** Get list of possibile tag name completions */
  TQValueList<KTextEditor::CompletionEntry>* getTagCompletions(int line, int col);
  /** Get list of possibile tag attribute completions */
  TQValueList<KTextEditor::CompletionEntry>* getAttributeCompletions(const TQString& tagName,const TQString& startsWith=TQString());
  /** Get list of possibile tag attribute value completions */
  TQValueList<KTextEditor::CompletionEntry>* getAttributeValueCompletions(const TQString& tagName, const TQString& attribute, const TQString& startsWith=TQString());
  /** Get list of possibile completions in normal text input (nt creating a tag) */
  TQValueList<KTextEditor::CompletionEntry>* getCharacterCompletions(const TQString& starstWith=TQString());
  /** Invoke code completion dialog for XML like tags according to the position (line, col), using DTD dtd. */
  bool xmlCodeCompletion(int line, int col);
  /** Returns list of values for attribute. If deleteResult is true after the call,
  the caller must delete the returned list. */
  TQStringList* tagAttributeValues(const TQString& dtdName, const TQString& tag, const TQString& attribute, bool &deleteResult);
  /** Brings up list of code completions */
  void showCodeCompletions( TQValueList<KTextEditor::CompletionEntry> *completions );
  /** Called whenever a user inputs text in an XML type document. */
  bool xmlAutoCompletion(int , int , const TQString & );
  /** Called whenever a user inputs text in a script type document. */
  bool scriptAutoCompletion(int line, int col, const TQString &insertedString);
  /** Returns true if the number of " (excluding \") inside text is even. */
  bool evenQuotes(const TQString &text);
  void handleCodeCompletion();
  bool isDerivatedFrom(const TQString& className, const TQString &baseClass);
};

#endif

