/*
 * Occurrences.h
 *
 *  Created on: 9. 2. 2014
 *	  Author: Jan Travnicek
 */

#pragma once

#include <string/LinearString.h>
#include <tree/ranked/RankedTree.h>

#include "Run.h"
#include <automaton/FSM/DFA.h>
#include <automaton/TA/DFTA.h>
#include <automaton/TA/UnorderedDFTA.h>
#include <automaton/PDA/InputDrivenDPDA.h>
#include <automaton/PDA/VisiblyPushdownDPDA.h>
#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
#include <automaton/PDA/DPDA.h>

#include <alib/deque>

namespace automaton {

namespace run {

/**
 * \brief
 * Implementation of automaton run over its input reporting occurrences .
 */
class Occurrences {
public:
	/**
	 * Automaton occurrences run implementation.
	 *
	 * \tparam SymbolType type of symbols of the string and terminal symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the string where the automaton passed a final state
	 */
	template < class SymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );

	/**
	 * \override
	 *
	 * \tparam SymbolType type of symbols of tree nodes and terminal symbols of the runned automaton
	 * \tparam RankType type of ranks of tree nodes and terminal symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the tree where the automaton passed a final state (as in the postorder traversal)
	 */
	template < class SymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::DFTA < SymbolType, StateType > & automaton, const tree::RankedTree < SymbolType > & tree );

	/**
	 * \override
	 *
	 * \tparam SymbolType type of symbols of tree nodes and terminal symbols of the runned automaton
	 * \tparam RankType type of ranks of tree nodes and terminal symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the tree where the automaton passed a final state (as in the postorder traversal)
	 */
	template < class SymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::UnorderedDFTA < SymbolType, StateType > & automaton, const tree::UnorderedRankedTree < SymbolType > & tree );

	/**
	 * \override
	 *
	 * \tparam InputSymbolType type of symbols of the string and terminal symbols of the runned automaton
	 * \tparam PushdownStoreSymbolType type of pushdown store symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the tree where the automaton passed a final state
	 */
	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string );

	/**
	 * \override
	 *
	 * \tparam InputSymbolType type of symbols of the string and terminal symbols of the runned automaton
	 * \tparam PushdownStoreSymbolType type of pushdown store symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the tree where the automaton passed a final
	 */
	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string );

	/**
	 * \override
	 *
	 * \tparam InputSymbolType type of symbols of the string and terminal symbols of the runned automaton
	 * \tparam PushdownStoreSymbolType type of pushdown store symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the tree where the automaton passed a final state
	 */
	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string );

	/**
	 * \override
	 *
	 * \tparam InputSymbolType type of symbols of the string and terminal symbols of the runned automaton
	 * \tparam PushdownStoreSymbolType type of pushdown store symbols of the runned automaton
	 * \tparam StateType type of states of the runned automaton
	 *
	 * \param automaton the runned automaton
	 * \param string the input of the automaton
	 *
	 * \return set of indexes to the tree where the automaton passed a final state
	 */
	template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
	static ext::set < unsigned > occurrences ( const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string );

};

template < class SymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
	ext::tuple < bool, StateType, ext::set < unsigned > > res = Run::calculateState ( automaton, string );

	return std::get < 2 > ( res );
}

template < class SymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::DFTA < SymbolType, StateType > & automaton, const tree::RankedTree < SymbolType > & tree ) {
	ext::tuple < bool, StateType, ext::set < unsigned > > res = Run::calculateState ( automaton, tree );

	return std::get < 2 > ( res );
}

template < class SymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::UnorderedDFTA < SymbolType, StateType > & automaton, const tree::UnorderedRankedTree < SymbolType > & tree ) {
	ext::tuple < bool, StateType, ext::set < unsigned > > res = Run::calculateState ( automaton, tree );

	return std::get < 2 > ( res );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string ) {
	ext::tuple < bool, StateType, ext::set < unsigned >, ext::deque < PushdownStoreSymbolType > > res = Run::calculateState ( automaton, string );

	return std::get < 2 > ( res );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string ) {
	ext::tuple < bool, StateType, ext::set < unsigned >, ext::deque < PushdownStoreSymbolType > > res = Run::calculateState ( automaton, string );

	return std::get < 2 > ( res );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string ) {
	ext::tuple < bool, StateType, ext::set < unsigned >, ext::deque < PushdownStoreSymbolType > > res = Run::calculateState ( automaton, string );

	return std::get < 2 > ( res );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::set < unsigned > Occurrences::occurrences ( const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const string::LinearString < InputSymbolType > & string ) {
	ext::tuple < bool, StateType, ext::set < unsigned >, ext::deque < PushdownStoreSymbolType > > res = Run::calculateState ( automaton, string );

	return std::get < 2 > ( res );
}

} /* namespace run */

} /* namespace automaton */

