#ifndef ADJECTIVE_H_INCLUDED
#define ADJECTIVE_H_INCLUDED

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

#include "boost/algorithm/string.hpp"

#include "grammarCase.h"

namespace AJ
{

	struct AdjectiveRecord
	{
		std::wstring nominativeMaleForm;

		bool standardShortFormAvailable;

		std::wstring specialShortForm;

		std::vector<TranslationUnit> translationUnitArr;

		AdjectiveRecord();
		AdjectiveRecord(std::wstring line);

		bool operator<(const AdjectiveRecord& n) const
		{
			return nominativeMaleForm < n.nominativeMaleForm;
		}
	};


	extern std::vector<AdjectiveRecord> AdjectiveRecordArr;


	struct AdjectiveStruct
	{
		NounGrammaticalCase grammaticalCase;

		NounCount count;
		NounGender gender;
		
		bool isDeclentionAnimated;

		AdjectiveRecord adjectiveRecord;

		bool operator<(const AdjectiveStruct& n) const
		{
			if (grammaticalCase != n.grammaticalCase)
			{
				return grammaticalCase < n.grammaticalCase;
			}
			else
			{
				if (count != n.count)
				{
					return count < n.count;
				}
				else
				{
					if (gender != n.gender)
					{
						return gender < n.gender;
					}
					else
					{
						if (isDeclentionAnimated != n.isDeclentionAnimated)
						{
							return isDeclentionAnimated < n.isDeclentionAnimated;
						}
						else
						{
							return adjectiveRecord < n.adjectiveRecord;
						}
					}
				}
			}
		}
	};


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



	enum AdjectiveDeclencion
	{
		IFORM_MALE_INANIMATE = 0,
		IFORM_MALE_ANIMATE,
		UFORM_MALE_INANIMATE,
		UFORM_MALE_ANIMATE,
		UOFORM_MALE_INANIMATE,
		UOFORM_MALE_ANIMATE,
		IOFORM_MALE_INANIMATE,
		IOFORM_MALE_ANIMATE,
		IFORM_FEMALE_INANIMATE,
		IFORM_FEMALE_ANIMATE,
		UFORM_FEMALE_INANIMATE,
		UFORM_FEMALE_ANIMATE,
		UOFORM_FEMALE_INANIMATE,
		UOFORM_FEMALE_ANIMATE,
		IOFORM_FEMALE_INANIMATE,
		IOFORM_FEMALE_ANIMATE,
		IFORM_NEUTRAL,
		UFORM_NEUTRAL,
		UOFORM_NEUTRAL,
		IOFORM_NEUTRAL,
	};


	struct AdjectiveDeclencionCaseTableRecord
	{
		AdjectiveDeclencion adjectiveDeclencion;
		std::vector<GrammaticalTableRecord> grammaticalCaseTable;
	};

	extern std::vector<AdjectiveDeclencionCaseTableRecord> adjectiveDeclencionCaseTable;


	AdjectiveDeclencion WStringToAdjectiveDeclencion(std::wstring str);


	struct AdjectiveEndingDivision
	{
		std::wstring base;
		std::wstring ending;

		enum DivisionCase
		{
			DC_COMMON = 0
		} divisionCase;

		bool operator<(const AdjectiveEndingDivision& other) const
		{
			if (base != other.base)
			{
				return base < other.base;
			}
			else
			{
				if (ending != other.ending)
				{
					return ending < other.ending;
				}
				else
				{
					return divisionCase < other.divisionCase;
				}
			}
		}
	};

	std::set<AdjectiveEndingDivision> getPossibleAdjectiveEndingDivisionSet(std::wstring noun);


	typedef std::tuple <
		AdjectiveDeclencion,
		NounCount,
		NounGrammaticalCase
	> AdjectiveTuple;

	std::vector<AdjectiveTuple> GetPossibleTupleArr(std::wstring ending);

	bool AdjectiveIsInDictionary(std::wstring nominative);
	AdjectiveRecord GetAdjectiveRecordFromDictionary(std::wstring nominative);

	
	
	//std::set<std::wstring> GetAdjectiveNominative(std::wstring base, AdjectiveDeclencion declencion, NounCount nounCount);
	std::set<std::wstring> GetNominativeMaleSingular(std::wstring base);

	void SetupDeclentionMap();
	bool AdjectiveFitsDeclention(AdjectiveRecord record, AdjectiveTuple tuple);

	bool IsDeclencionAnimated(AdjectiveDeclencion declention);
	NounGender GetGenderFromDeclencion(AdjectiveDeclencion declention);

	void FillDivisionCaseMaps();


	std::set<AdjectiveStruct> RecognizeAdjective(std::wstring noun);


	void LoadAdjectiveDeclencionCaseTable();


	void LoadFrequentAdjectiveSet();



} //namespace AJ


#endif //ADJECTIVE_H_INCLUDED
