/*
    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 "UnitStub.h"
#include "ResourcesHolder.h"

namespace LexicalUnits
{
	namespace MEParser
	{
		boost::regex UnitStub::m_PatRegex(" *(<pat>)? *#(.*) *\\( *\"(.+)\" *\\) *(<.pat>)? *",boost::regex::icase);
                boost::regex UnitStub::m_HeadNumRegex("\\$\\+?([1-9-]+)H");
		
		UnitStub::UnitStub(const std::string &lubase, const std::string & pat, const std::string & type, 
			const std::string &head_cond, const std::string &f ) : m_pCondition(NULL)
		{
			Parse(lubase,pat, type, head_cond, f);
		}
		UnitStub::~UnitStub()
		{
			if( m_pCondition )
				delete m_pCondition;
		}

		int UnitStub::GetBaseIndex() const
		{
			return m_iBaseIndex;
		}

		LexicalUnitType::TYPES UnitStub::GetType() const
		{
			return m_tType;
		}

		const std::string& UnitStub::GetMakro() const
		{
			return m_sMakroName;
		}

		JOSKIPI::Operators::CCondition* UnitStub::RetrieveCondition()
		{
			JOSKIPI::Operators::CCondition* j = m_pCondition;

			m_pCondition = NULL;

			return j;
		}

		bool UnitStub::IsUsable() const
		{
			return m_pCondition != NULL;
		}

		int UnitStub::operator < (const UnitStub& stub)
		{
			return strcmp(m_sMakroName.c_str(), stub.m_sMakroName.c_str());
		}

		void UnitStub::Parse(const std::string &lubase, const std::string & pat, const std::string & type, 
			const std::string &head_cond, const std::string &f )
		{
			if(!ParsePat(pat))
				throw std::runtime_error( std::string("Error in LU pattern: " ) + pat ) ;
			
			m_iBaseIndex =  Corpus::CWordDictionary::GetInstance()->Add(lubase);
			m_tType = LexicalUnitType::FromString(type);

			std::string op = head_cond;
                        //std::cout << op << std::endl;
			boost::algorithm::replace_all( op, "$H", "0");
                        op = boost::regex_replace( op, UnitStub::m_HeadNumRegex, "$1");
                        //std::cout << "------------"<<std::endl<<op << std::endl;
			m_pCondition = ResourcesHolder::GetJOSKIPIParser()->ParseCondition(op);

			m_FlexClass = Corpus::CTag::GetFlexClass(f);

		}

		
		bool UnitStub::ParsePat(const std::string &pat)
		{
			m_vVars.clear();
			boost::smatch match;

			if( boost::regex_match(pat,match,m_PatRegex) )
			{
				m_sMakroName = match[2];
				boost::erase_all(m_sMakroName, "#");
				
				Corpus::CWordDictionary *dict = Corpus::CWordDictionary::GetInstance();
				std::string varstr = match[3] ;

					
				std::vector<std::string> vars;

				boost::split(vars, varstr, boost::is_any_of(","));

				if(!vars.size())
					return false;

				for( size_t i = 0;i<vars.size() ;i++ )
				{
					std::string v = vars[i];
					boost::trim(v);
					boost::erase_all(v, "\"");

					int var_id = dict->Add(v);
//                                        std::cout << " adding " << v << "with id "<< var_id<< " " << dict->GetAt(var_id)<< std::endl;
					m_vVars.push_back(var_id);
				}

				return true;
			}

			return false;
		}

		size_t UnitStub::GetNumberOfVars() const
		{
			return m_vVars.size();
		}

		int UnitStub::GetVarBaseId(size_t varNo) const
		{
			return m_vVars[varNo];
		}
		Corpus::TFlexClass UnitStub::GetFlexClass() const
		{
			return m_FlexClass;
		}

	}//namespace MEParser
}//namespace LexicalUnits

