/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.

    This program 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 LICENSE and COPYING files for more details.
*/

#include "lex_headers.h" 
#include "FlexME.h"

namespace LexicalUnits
{
	FlexME::FlexME(int baseId, const std::vector<boost::shared_ptr<Word> > &constituents,
				JOSKIPI::Operators::CCondition* head_search,
				JOSKIPI::Operators::CCondition* operator_constraint,Corpus::TFlexClass fc )
					: LexicalUnit(constituents, baseId, fc),
					 m_pHeadSearch(head_search),
					m_pCondition(operator_constraint)
	{
	}

	FlexME::~FlexME()
	{
		delete m_pHeadSearch;
		delete m_pCondition;
	}

	std::string FlexME::ToXmlString()
	{
		throw std::string("MultiwordExpression::ToXmlString not implemented");
		//TODO FlexME::ToXmlString()
		return "";
	}

	bool FlexME::CheckCurrentPosition ( Corpus::CSentence &sentence, size_t &head_index,
										std::set<size_t> &constituents )
	{
		head_index = 0;
		constituents.clear();

		if( (sentence.Size() - sentence.GetPosition() ) < (int)m_vConstituents.size() )
			return false;

		int currPos = sentence.GetPosition();

		std::set<size_t> foundConstituents;
		// for each subsequent position in sentence
		for(size_t i = 0; i < m_vConstituents.size(); i++)
		{
			Corpus::CToken *pToken = sentence.GetToken((int) i + currPos );

			bool foundAnyNewConstituent = false;
			//for each constituent on current position
			for(size_t j = 0; j < m_vConstituents.size() && !foundAnyNewConstituent; j++)
			{
				// if this constituent was found - then ok, carry on
				if( foundConstituents.count(j) )
					continue;
				for(size_t lex_no = 0; lex_no < pToken->GetLexCount() && !foundAnyNewConstituent; lex_no++)
				{
					Corpus::CLexem *pDisamb = pToken->GetLexem(lex_no);

					if(!pDisamb->GetDisamb() )
						continue;
					if( *m_vConstituents[j] == *pDisamb)
					{
						foundAnyNewConstituent = true;
						foundConstituents.insert(j);
					}
				}
			}

			// if we found new constituent, then add its position
			if(foundAnyNewConstituent)
				constituents.insert((size_t) currPos + i);
			else// otherwise quit - we want be able to found all constituents...
				return false;
		}

		if( foundConstituents.size() != m_vConstituents.size() )
			return false;

		sentence.Goto( currPos );
		if( !m_pCondition->Evaluate(sentence) )
			return false;

		bool headFound = false;
		// search for head
		for(size_t i = 0; i < m_vConstituents.size() && !headFound; i++)
		{
			int actualPos = currPos+(int) i;
			sentence.Goto( actualPos );
			if( m_pHeadSearch->Evaluate(sentence) )
			{
				sentence.Goto(currPos);
				constituents.erase((size_t) actualPos);
				head_index = actualPos;
				headFound = true;
			}
		}

		if( !headFound )
		{
			///\todo TODO log error message, should do some global logging mechanizm (in Corpus possibly)
			constituents.clear();
			return false;
		}

		return true;
	}


}//namespace LexicalUnits


