#ifndef __LemFST
#define __LemFST

#include <fst/fst.h>
#include <list>
#include <wchar.h>

#define fstMAXPATH 100
using namespace fst;
class LemFST
{
public:
	LemFST(const char*);
	~LemFST(void);


//////////////////////////////////////////////////////////////////////////////
	typedef StdFst::Arc::Label Char; // Pojedynczy znak
	typedef StdFst::StateId State; // Stan
	
	typedef std::list<Char> Word; // Lista znakow. 
	typedef std::list<Char>::iterator WordIt; // Iterator po lisice znakow


	typedef ArcIterator<StdFst> ArcsIt; // Iterator po krawedziach
	typedef struct {
		ArcsIt* it;		// Krawedzie wychodzace (Iterator)
		State id;		// Numer stanu
		State prev;		// Poprzednik stanu
		Char symbol;	// Symbol po jakim przeszlismy z prev do id
		bool checked;	// Czy stan byl juz brany pod uwage jako koncowy
	} StateInfo;

	typedef std::list<StateInfo> Path;	// Sciezka stanow (wlasc. stos)
	typedef Path::iterator PathIt;		// Iterator po Sciezce
	typedef Path::reverse_iterator PathRevIt; // Odwrotny iterator po Scieze
	
	
	// Operacje na automacie:
	StdFst *fst; // Automat LEMa
	State start();
	bool accept(State);
	State next(State, Char); // Go to next state by Char
	State next(State, Word); // Go to end of the Word





	// Przeszukiwanie automatu:
	Path path;
    long cont(State, Word*, int); // Return a path from state to finish state;



	// Pomocnicze:
	inline const StateInfo getStateInfo(State, State, Char);


	static const State noStateId = fst::kNoStateId;

	/** Zwraca ciag wchar_t zbudowany ze slowa w */
	inline static char* wordToChar(Word* w) {
		int len = w->size();
		WordIt it;
		char* ret = new char[len+1];
		int i=0;
		for(it=w->begin(); it!=w->end(); it++) {
			ret[i++] = static_cast<char>(*it);
		}
		ret[i]='\0';
		return ret;
	}

    /** Zwraca ciag wchar_t zbudowany ze slowa w */
	inline static wchar_t* wordToWChar(Word* w) {
		int len = w->size();
		WordIt it;
		wchar_t* ret = new wchar_t[len+1];
		int i=0;
		for(it=w->begin(); it!=w->end(); it++) {
			ret[i++] = static_cast<wchar_t>(*it);
		}
		ret[i]=L'\0';
		return ret;
	}



	/** Zwraca slowo Word* na podstawie ciagu wchar_t */
	inline static Word* charToWord(const wchar_t* ch) {
		int i =0;
		Word *w = new Word();
		for(; ch[i]!=L'\0'; i++)  {
			w->push_back((int)ch[i]);
		}
		return w;
	}
    
    /** Zwraca slowo Word* na podstawie ciagu wchar_t */
	inline static Word* charToWord(const char* ch) {
		int i =0;
		Word *w = new Word();
		for(; ch[i]!='\0'; i++)  {
			w->push_back((int)ch[i]);
		}
		return w;
	}

};

#endif
