/*
 * Determinize.h
 *
 *  Created on: 16. 1. 2014
 *	  Author: Jan Vesely
 */

#ifndef DETERMINIZE_H_
#define DETERMINIZE_H_

#include <core/multipleDispatch.hpp>
#include <set>

#include <automaton/common/State.h>
#include <automaton/Automaton.h>
#include <automaton/FSM/DFA.h>
#include <automaton/PDA/DPDA.h>
#include <automaton/PDA/InputDrivenDPDA.h>
#include <automaton/PDA/SinglePopDPDA.h>
#include <automaton/PDA/VisiblyPushdownDPDA.h>
#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
#include <automaton/TM/OneTapeDTM.h>
#include <automaton/TA/DFTA.h>

namespace automaton {

namespace determinize {

/**
 * Class for running determinization algorithm on fsm.
 */
class Determinize : public std::SingleDispatch<automaton::Automaton, automaton::AutomatonBase> {
public:

	/**
	 * @param nfsm nondeterministic final-state machine given for determinization
	 * @return DFA
	 * Runs determinization algorithm on nondeterministic fsm given in constructor.
	 */
	static automaton::Automaton determinize(const automaton::Automaton& nfa);

	static automaton::DFA determinize(const automaton::DFA& nfa);
	static automaton::DFA determinize(const automaton::NFA& nfa);
	static automaton::DFA determinize(const automaton::MultiInitialStateNFA& nfa);
	static automaton::DPDA determinize(const automaton::DPDA& dpda);
	static automaton::DPDA determinize(const automaton::NPDA& dpda);
	static automaton::SinglePopDPDA determinize(const automaton::SinglePopDPDA& dpda);
	static automaton::VisiblyPushdownDPDA determinize(const automaton::VisiblyPushdownDPDA& nondeterministic);
	static automaton::VisiblyPushdownDPDA determinize(const automaton::VisiblyPushdownNPDA& nondeterministic);
	static automaton::InputDrivenDPDA determinize(const automaton::InputDrivenDPDA& nfa);
	static automaton::InputDrivenDPDA determinize(const automaton::InputDrivenNPDA& nfa);
	static automaton::RealTimeHeightDeterministicDPDA determinize(const automaton::RealTimeHeightDeterministicDPDA& nondeterministic);
	static automaton::RealTimeHeightDeterministicDPDA determinize(const automaton::RealTimeHeightDeterministicNPDA& nondeterministic);
	static automaton::DFTA determinize(const automaton::DFTA& nfta);
	static automaton::DFTA determinize(const automaton::NFTA& nfta);
	static automaton::OneTapeDTM determinize(const automaton::OneTapeDTM& nfta);

	static Determinize& getInstance() {
		static Determinize res;
		return res;
	}
};

} /* namespace determinize */

} /* namespace automaton */

#endif /* DETERMINIZE_H_ */