/*
 * RTEOptimize.h
 *
 *  Created on: 1. 4. 2019
 *	  Author: Jan Travnicek
 */

#ifndef _RTE_OPTIMIZE_H__
#define _RTE_OPTIMIZE_H__

#include <alib/algorithm>
#include <alib/iterator>

#include <rte/formal/FormalRTE.h>
#include <rte/formal/FormalRTEElements.h>

#include <exception/CommonException.h>

namespace rte {

namespace simplify {

class RTEOptimize {
public:

	template < class SymbolType >
	static rte::FormalRTE < SymbolType > optimize( const rte::FormalRTE < SymbolType > & rte );
	template < class SymbolType >
	static rte::FormalRTEStructure < SymbolType > optimize( const rte::FormalRTEStructure < SymbolType > & rte );
	template < class SymbolType >
	static void optimize( rte::FormalRTEElement < SymbolType > & element );
private:
	template < class SymbolType >
	static ext::smart_ptr < rte::FormalRTEElement < SymbolType > > optimizeInner( const rte::FormalRTEElement < SymbolType > & node );

	template < class SymbolType >
	static bool S( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A1( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A2( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A3( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A4( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A5( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A6( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A7( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A8( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool A9( rte::FormalRTEElement < SymbolType > * & node );
/*	template < class SymbolType >
	static bool A10( rte::FormalRTEElement < SymbolType > * & node );*/
	template < class SymbolType >
	static bool A11( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V1( rte::FormalRTEElement < SymbolType > * & node );
/*	template < class SymbolType >
	static bool V2( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V3( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V4( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V5( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V6( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V8( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V9( rte::FormalRTEElement < SymbolType > * & node );
	template < class SymbolType >
	static bool V10( rte::FormalRTEElement < SymbolType > * & node );*/

	template < class SymbolType >
	static bool X1( rte::FormalRTEElement < SymbolType > * & node );
};

template < class SymbolType >
FormalRTE < SymbolType > RTEOptimize::optimize( const FormalRTE < SymbolType > & rte ) {
	return rte::FormalRTE < SymbolType > ( RTEOptimize::optimize ( rte.getRTE ( ) ) );
}

template < class SymbolType >
FormalRTEStructure < SymbolType > RTEOptimize::optimize( const FormalRTEStructure < SymbolType > & rte ) {
	ext::smart_ptr < FormalRTEElement < SymbolType > > optimized = optimizeInner( rte.getStructure ( ) );

	return rte::FormalRTEStructure < SymbolType > ( * optimized );
}

} /* namespace simplify */

} /* namespace rte */

#include "RTEOptimizeFormalPart.hpp"

#endif /* _RTE_OPTIMIZE_H__ */
