/*
 * LatexTable.h
 *
 *  Created on: 6. 11. 2017
 *      Author: Jan Travnicek
 */

#ifndef LATEX_TABLE_H_
#define LATEX_TABLE_H_

#include <ostream>
#include <alib/set>
#include <alib/map>
#include <alib/list>
#include <alib/utility>
#include <alib/vector>

#include <exception/CommonException.h>
#include <string/String.h>

#include <automaton/FSM/DFA.h>

#include "common/converterCommon.hpp"

#include <factory/StringDataFactory.hpp>
#include <string/string/LinearString.h>
#include <regexp/string/UnboundedRegExp.h>

namespace convert {

class LatexTable {
public:
	template < class SymbolType, class StateType >
	static void convert(std::ostream& out, const automaton::DFA < SymbolType, StateType > & a);

	template < class T >
	static std::string convert ( const T & automaton ) {
		std::stringstream ss;
		convert ( ss, automaton );
		return ss.str ( );
	}
};

template < class SymbolType, class StateType >
void LatexTable::convert(std::ostream& out, const automaton::DFA < SymbolType, StateType > & a) {
	size_t symbols = a.getInputAlphabet ( ).size ( );
	out << "\\begin{tabular}{|lr||";
	for ( size_t i = 0; i < symbols; ++ i )
		out << "c|";
	out << "l}" << std::endl;
	out << "\\hline" << std::endl;
	out << "                  &   & ";
	for ( const SymbolType & symbol : a.getInputAlphabet ( ) )
		out << replace ( factory::StringDataFactory::toString ( symbol ), "\"", "\\\"" ) << " & ";
	out << "\\hspace*{14cm}\\\\" << std::endl;
	out << "\\hline" << std::endl;

	for ( const StateType & source : a.getStates ( ) ) {
		out << "\\hline" << std::endl;
		if ( a.getFinalStates ( ).count ( source ) && a.getInitialState ( ) == source )
			out << "$\\leftrightarrow$ & ";
		else if ( a.getFinalStates ( ).count ( source ) )
			out << "$\\leftarrow$      & ";
		else if ( a.getInitialState ( ) == source )
			out << "$\\rightarrow$     & ";
		else
			out << "                  & ";

		out << replace ( factory::StringDataFactory::toString ( source ), "\"", "\\\"" ) << " & ";

		for ( const SymbolType & symbol : a.getInputAlphabet ( ) ) {
			auto transition = a.getTransitions ( ).find ( ext::make_pair ( source, symbol ) );
			if ( transition == a.getTransitions ( ).end ( ) )
				out << "- & ";
			else
				out << replace ( factory::StringDataFactory::toString ( transition->second ), "\"", "\\\"" ) << " & ";
		}

		out << "\\\\" << std::endl;
	}

	out << "\\hline" << std::endl;
	out << "\\end{tabular}" << std::endl;
}

} /* namespace convert */

#endif /* LATEX_TABLE_H_ */
