#ifndef VERB_H_INCLUDED
#define VERB_H_INCLUDED

#include <string>
#include <map>
#include <set>
#include <vector>
#include <fstream>

#include "boost/algorithm/string.hpp"

#include "grammarCase.h"

namespace VB
{
	struct VerbRecord
	{
		std::wstring infinitive;
		bool canBePrefixed;
		bool canBeNotPrefixed;
		bool canBePerfect;
		bool canBeImperfect;

		std::vector<TranslationUnit> translationUnitArr;

		VerbRecord();

		VerbRecord(std::wstring line);

		bool operator<(const VerbRecord& v) const
		{
			return infinitive < v.infinitive;
		}

	};


	extern std::vector<VerbRecord> VerbRecordArr;

	enum VerbParams
	{
		VP_INFINITIVE = 0,
		VP_PAST_MALE_SINGULAR,
		VP_PAST_FEMALE_SINGULAR,
		VP_PAST_NEUTER_SINGULAR,
		VP_PAST_PLURAL,
		VP_PRESENT_FIRSTPERSON_SINGULAR,
		VP_PRESENT_SECONDPERSON_SINGULAR,
		VP_PRESENT_THIRDPERSON_SINGULAR,
		VP_PRESENT_FIRSTPERSON_PLURAL,
		VP_PRESENT_SECONDPERSON_PLURAL,
		VP_PRESENT_THIRDPERSON_PLURAL,
		VP_SIZE
	};

	enum VerbConjunction
	{
		VC_FIRST_ET = 0,
		VC_FIRST_AT,
		VC_FIRST_OT,
		VC_FIRST_IT,
		VC_FIRST_YT,
		VC_FIRST_YAT,
		VC_SECOND_IT,
		VC_SECOND_ET,
		VC_SECOND_AT,
		VC_SIZE
	};

	struct VerbConjunctionTableRecord
	{
		VerbConjunction conjunction;

		std::wstring ending;
	};

	struct VerbParamsTableRecord
	{
		VerbParams verbParams;
		std::vector<VerbConjunctionTableRecord> verbConjunctionTable;
	};


	extern std::vector<VerbParamsTableRecord> VerbParamsTable;


	struct VerbStruct
	{
		VerbParams verbParams;
		std::wstring selfEnding;

		VerbRecord verbRecord;

		
		bool operator<(const VerbStruct& v) const
		{
			if (verbParams != v.verbParams)
			{
				return verbParams < v.verbParams;
			}
			else
			{
				if (selfEnding != v.selfEnding)
				{
					return selfEnding < v.selfEnding;
				}
				else
				{
					return verbRecord < v.verbRecord;
				}
			}
		}
	};


	VerbParams WStringToVerbParams(std::wstring str);
	std::wstring VerbParamsToWString(VerbParams verbParams);
	VerbConjunction WStringToVerbConjunction(std::wstring str);

	bool VerbIsInDictionary(std::wstring verbInfinitive);
	VerbRecord GetVerbRecordFromDictionary(std::wstring verbInfinitive);

	std::wstring cutSelfEndingIfPossible(std::wstring& verb);

	std::vector<std::wstring> GetAllVerbEndingArr();


	struct VerbEndingDivision
	{
		std::wstring base;
		std::wstring ending;
		
		bool operator<(const VerbEndingDivision& other) const
		{
			if (base != other.base)
			{
				return base < other.base;
			}
			else
			{
				return ending < other.ending;
			}
		}
	};


	std::set<VerbEndingDivision> getPossibleVerbEndingDivisionSet(std::wstring verb);

	std::set<std::pair<VerbParams, VerbConjunction>> getAllPossibleVerbParamsAndConjunctions(std::wstring ending);

	std::wstring GetVerbInfinitive(std::wstring modifiedBase, VerbConjunction verbConjunction);

	std::set<VerbStruct> RecognizeVerb(std::wstring verb);


	void LoadVerbConjunctionTable();

	void LoadFrequentWordSet();

	

} //namespace VB

#endif //VERB_H_INCLUDED
