#ifndef KANJICONVERT_H
#define KANJICONVERT_H

#include "dicthiragana.h"
#include "candidacylistbox.h"
#include "inputmode.h"
#include <qobject.h>
#include <qevent.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qptrlist.h>
#include <qintdict.h>

class SockKanjiClient;
class CandidacyListBox;
class PreeditArea;
class KanjiConvert;
class FuncPtr;

enum FuncName {     // Function name definition
  //GETCANDIDACYLIST,
  NEXTCANDIDACY,
  PREVIOUSCANDIDACY,
  CONVERTALLPHASES,
  CONVERTCURRPHASE,
  //CHANGEALLTOHIRA,
  APPENDCHAR,
  DELETEBACKWARD,
  DECIDEALLPHASES,
  DECIDECURRPHASE,
  CANCELCONVERSION,
  LENGTHENPHASE,
  SHORTENPHASE,
  INPUTSPACECHAR,
  CONVERTTOHIRA,
  CONVERTTOKANA,
  CONVERTTOHANKAKU,
  CONVERTTOZENKAKU,
  NONE,          // 何もしない
  KEYFORWARD     // キーイベントをクライアントに戻す
};

enum ConvStatus {   // Kanji conversion status definition
  NONE_YOMI = 0,    // 読みが入力されていない状態
  INPUTING_YOMI,    // 読みが入力されており、変換されていない状態
  CONVERTING_YOMI,  // 読みが漢字に変換された状態
  SHOWING_LIST,     // 変換中の候補一覧が表示されている状態
  CHANGING_LENGTH,  // 文節の長さを変更している状態
  //EDITING_PHASE,  // 変換された文節を編集している状態
  NUM_OF_CONVSTATUS = 5
};

typedef void      (KanjiConvert::*pmfunc)();
typedef FuncName  FuncNameArray[NUM_OF_CONVSTATUS];

class KanjiConvert : public QObject {
  Q_OBJECT

public:
  KanjiConvert();
  ~KanjiConvert();
  void    init();
  void    clear();
  bool    processKeyEvent(const QKeyEvent&);
  void    setFont(QFont);
  void    setPreeditPoint(QPoint);
  
public slots:
  void    setInputMode(const InputMode&);

signals:
  void decidePhases(const QString&);

protected slots:
  void    slotConvertAllPhases(const QStringList&);
  void    slotReconvtPhases(const QStringList&);
  void    slotCandidacyList(const QStringList&);
  void    slotYomigana(const QString&);
  void    slotDecidePhases(QListBoxItem* item);

protected:
  void    toolboxHide();
  //void    getCandidacyList();
  //void    pressSpaceKey();
  void    convertAllPhases();
  void    convertCurrPhase();
  void    nextCandidacy();
  void    previousCandidacy();
  //QString changeAlltoHira();
  //void    appendChar(QChar);
  void    appendChar(const QKeyEvent&);
  void    deleteBackward();
  //void    removeYomi(uint index, uint len);
  void    decideAllPhases();
  void    decideCurrPhase();
  void    cancelConversion();
  void    lengthenPhase();
  void    shortenPhase();
  void    inputSpaceChar();
  void    convertToHira();
  void    convertToKata();
  void    convertToHankaku();
  void    convertToZenkaku();

  FuncNameArray* newFuncNameArray(FuncName, FuncName, FuncName, FuncName, FuncName) const;
  static void  init_funcptrdict();

private:
  int         _curphsidx;      // current phase index
  QString     _curphsyomi;     // yomigana of current phase
  QString     _inputkeys;      // input roma string
  QString     _yomigana;       // yomigana string
  QStringList _convtkanjilist; // kanji string list converted
  ConvStatus  _stat;           // kanji conversion status
  InputMode   _mode;           // input mode
  QPoint                    _spotpreedit;
  DictHiragana              _dict;
  SockKanjiClient*          _sockkanjiclt;
  PreeditArea*              _preedit;
  CandidacyListBox*         _candlist;
  QIntDict<FuncNameArray>   _functbl;
  
  static QIntDict<FuncPtr>   funcptrdict;  // dictionary of function pointer
};


class FuncPtr {
public:
  FuncPtr() { }
  FuncPtr(QString s, pmfunc p) : _pmf(p), _name(s) { }
  inline pmfunc  ptr() const { return _pmf; }
  inline QString  funcName() const { return _name; }

private:  
  pmfunc   _pmf;  // pointer to member function of KanjiConvert class
  QString  _name;
};


#endif // KANJICONVERT_H










