/*
 * ExactSubtreeAutomaton.cpp
 *
 *  Created on: 7. 4. 2015
 *      Author: Jan Travnicek
 */

#include "ExactSubtreeAutomaton.h"
#include <exception/AlibException.h>
#include <tree/Tree.h>
#include <tree/ranked/PrefixRankedTree.h>
#include <automaton/Automaton.h>
#include <automaton/PDA/InputDrivenNPDA.h>

#include <deque>

namespace arbology {

namespace exact {

automaton::Automaton ExactSubtreeAutomaton::construct ( const tree::Tree & text ) {
	return getInstance ( ).dispatch ( text.getData ( ) );
}

automaton::InputDrivenNPDA ExactSubtreeAutomaton::construct ( const tree::PrefixRankedTree & tree ) {
	alphabet::Symbol S = alphabet::symbolFrom ( 'S' );
	automaton::InputDrivenNPDA res ( automaton::State ( 0 ), S );

	for ( const alphabet::RankedSymbol & rankedSymbol : tree.getAlphabet ( ) ) {
		alphabet::Symbol symbol ( rankedSymbol );
		res.addInputSymbol ( symbol );
		res.setPushdownStoreOperation ( symbol, std::vector < alphabet::Symbol > { 1, S }, std::vector < alphabet::Symbol > { rankedSymbol.getRank ( ).getData ( ), S } );
	}

	int i = 1;

	for ( const alphabet::RankedSymbol & rankedSymbol : tree.getContent ( ) ) {
		alphabet::Symbol symbol ( rankedSymbol );

		res.addState ( automaton::State ( i ) );
		res.addTransition ( automaton::State ( i - 1 ), symbol, automaton::State ( i ) );
		res.addTransition ( automaton::State ( 0 ), std::move ( symbol ), automaton::State ( i ) );
		i++;
	}

	return res;
}

auto ExactSubtreeAutomatonPrefixRankedTree = ExactSubtreeAutomaton::RegistratorWrapper < automaton::InputDrivenNPDA, tree::PrefixRankedTree > ( ExactSubtreeAutomaton::getInstance ( ), ExactSubtreeAutomaton::construct );

} /* namespace exact */

} /* namespace arbology */