/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CEditorSpellChecker.h  -  description
                             -------------------
    begin                : December 18 2003
    copyright            : (C) 2003-2005 by Alexey Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/
#ifndef __CEDITORSPELLCHECKER_H__
#define __CEDITORSPELLCHECKER_H__

#include <FL/Fl.h>

#include <sptk3/sptk.h>
#include <sptk3/CStrings.h>
#include <sptk3/CVariant.h>
#include <sptk3/CWindow.h>
#include <sptk3/CDialog.h>
#include <sptk3/CEditor.h>
#include <sptk3/CToolBar.h>
#include <sptk3/CInput.h>
#include <sptk3/CListView.h>
#include <sptk3/CThemes.h>

#include <map>

/// @addtogroup gui GUI Classes
/// @{

/// CSpellOption represents an option of Aspell config.
class CSpellOption {
public:   
   std::string  m_name;  ///< Option name
   std::string  m_value; ///< Option value
public:
   /// Constructor
   CSpellOption(std::string name,std::string value);

   /// Copy constructor
   CSpellOption(const CSpellOption& co) {
      m_name = co.m_name;
      m_value = co.m_value;
   }

   /// Assigns a new value to the option
   CSpellOption& operator = (const char *value);

   /// Assigns a new value to the option
   CSpellOption& operator = (std::string value);
};

/// CSpellOptions is a map of CSpellOption.
class CSpellOptions : public std::map<std::string,CSpellOption> {

public:
   /// Default constructor
   CSpellOptions() {}
};

struct AspellSpeller;
struct AspellConfig;

/// CSpellChecker is a base class for Aspell interface.
class CSpellChecker : public CSpellOptions, public CDialog  {
   CInput        *m_wordInput;            ///< Input widget to show the misspelled word
   CInput        *m_replaceToInput;       ///< Input widget to show the replacement word
   CListView     *m_suggestionListView;   ///< List view widget to show the list of suggestions
   AspellSpeller *m_spellChecker;         ///< Pointer to the Aspell spell checker
#ifdef _WIN32
   std::string    m_personalDirectory;    ///< Full path to personal directory on Windows
#endif

   /// Loads all Aspell config options into list of options
   /// @param aconfig AspellConfig *, Aspell config structure
   /// @param options CSpellOptions &, config options (output)
   void getConfigStrings(AspellConfig *aconfig,CSpellOptions& options);

   /// Saves changed (local) Aspell config options from internal list of options
   /// @param aconfig AspellConfig *, Aspell config structure
   void setLocalOptions(AspellConfig *aconfig);

protected:
   static void cb_learn(Fl_Widget *,void *);       ///< Callback for the add word button
   static void cb_ignore(Fl_Widget *,void *);      ///< Callback for the ignore word button
   static void cb_suggest(Fl_Widget *,void *);     ///< Callback for the suggestion list click
   static void cb_replaceword(Fl_Widget *,void *); ///< Callback for the replace word button

   void learnAndClose();                           ///< Adds a word to personal dictionary and hides window to continue spelling
   void ignoreAndClose();                          ///< Adds a word to ignore list and hides window to continue spelling
   void checkForError();                           ///< Checks for error after the operation and throws CException if error is detected
public:

   /// Default constructor
   CSpellChecker();

   /// Destructor
   virtual ~CSpellChecker() { }

   /// Sets the dictionary for the spell checking
   /// @see getDictionaries for obtaining the list of available dictionaries
   void selectDictionary(std::string dictionary);

   /// Defines the directory where Aspell data (language) files are stored
   void languageDataDirectory(std::string path);

   /// Defines the directory where Aspell dictionary files are stored
   void dictionaryDirectory(std::string path);

   /// Downloads the list of installed dictionaries
   void getDictionaries(CStrings& dictionaries);

   /// Downloads the Aspell options
   void getOptions(CSpellOptions& options);

   /// Resets the spell check position. Purely virtual, should be implemented in the derived class.
   virtual void textStart()=0L;

   /// Gets the next word and advances the spell check position. Purely virtual, should be implemented in the derived class.
   virtual bool getNextWord(std::string& w,int& wordStart,int& wordEnd)     { return false; }

   /// Replaces the word and advances the spell check position. Purely virtual, should be implemented in the derived class.
   virtual bool replaceWord(const std::string& w,int wordStart,int wordEnd) { return false; }

   /// Spell checks the text. Uses textStart(), getNextWord(), and replaceWord() to go through the text.
   bool spellCheck();

   /// Access (read and write) to the particular Aspell option.
   CSpellOption& operator [] (std::string optionName);

#ifdef _WIN32
   /// Sets full path to personal directory on Windows
   void personalDirectory(std::string dir) { m_personalDirectory = dir; }

   /// Returns full path to personal directory on Windows
   std::string personalDirectory() const { return  m_personalDirectory; }
#endif
};

/// Specialized spell checker to use with CEditor class.
class CEditorSpellChecker : public CSpellChecker {
   CEditor     *m_editor;        ///< CEditor widget containing the spelling text
   unsigned    m_bufferPosition; ///< Current spell checking word buffer position
public:
   /// Constructor
   /// @param editor CEditor *, widget to work with
   CEditorSpellChecker(CEditor *editor) { m_editor = editor; m_bufferPosition = 0; }

   /// Resets the spell check position
   virtual void textStart();

   /// Gets the next word and advances the spell check position
   virtual bool getNextWord(std::string& w,int& wordStart,int& wordEnd);

   /// Replaces the word and advances the spell check position
   virtual bool replaceWord(const std::string& w,int wordStart,int wordEnd);
};   

/// @}

#endif
