/*
 * ConversionHandler.h
 *
 *  Created on: 23. 2. 2014
 *      Author: tomas
 */

#ifndef ALGORITHMCHOOSER_H_
#define ALGORITHMCHOOSER_H_

#include <list>

#include <exception/AlibException.h>
#include <factory/DataFactory.hpp>


namespace conversions
{

/**
 * Wraps all conversions.
 * Determine what formalism input, what is desired output and algorithm. Then perform conversion.
 */
class ConversionHandler
{
public:
    enum TAlgorithm
    {
        DEFAULT,

        /* FA to RE */
        BRZOZOWSKI_ALGEBRAIC,
        STATE_ELIMINATION,

        /* FA to RG */
        // FA to LRG,
        // FA to RRG

        /* RE to FA */
        BRZOZOWSKI_DERIVATION,
        THOMPSON_NFA,
        GLUSHKOV_NFA,

        /* RE to RG */


        /* RG to FA */
        // LRG to FSM
        // RRG to FSM

        /* RG to RE */
        // BRZOZOWSKI_ALGEBRAIC

        /* RG to RG */
        // RRG to LRG
        // LRG to RRG

    };

    enum TFormalism
    {
        FINITE_AUTOMATON,

        REGULAR_GRAMMAR,
        LEFT_REGULAR_GRAMMAR,
        RIGHT_REGULAR_GRAMMAR,

        LINEAR_GRAMMAR,
        LEFT_LINEAR_GRAMMAR,
        RIGHT_LINEAR_GRAMMAR,

        REGULAR_EXPRESSION_UNBOUNDED,
        REGULAR_EXPRESSION_FORMAL,

        UNKNOWN,
    };
    #define isGrammar(x) ( (x) == REGULAR_GRAMMAR || (x) == LEFT_REGULAR_GRAMMAR || (x) == RIGHT_REGULAR_GRAMMAR \
                        || (x) == LINEAR_GRAMMAR  || (x) == LEFT_LINEAR_GRAMMAR  || (x) == RIGHT_LINEAR_GRAMMAR )

    #define isRegExp(x) ( (x) == REGULAR_EXPRESSION_FORMAL || (x) == REGULAR_EXPRESSION_UNBOUNDED )

    ConversionHandler( std::list<sax::Token> & tokens, const std::string & target, const std::string & algorithm, std::ostream & out );
    void convert( void );

private:
    TFormalism parseFormalismFromString( const std::string & _target ) const;
    TFormalism parseFormalismFromTokens( void ) const;
    TAlgorithm parseAlgorithmFromString( const std::string & _algorithm ) const;

    void convertFSM( void );
    void convertFSMtoRE( void );
    void convertFSMtoREF( void );
    void convertFSMtoREU( void );
    void convertFSMtoRG( void );
    void convertFSMtoLRG( void );
    void convertFSMtoRRG( void );

    void convertRE( void );
    void convertREtoFSM( void );
    void convertREtoRG( void );
    void convertREtoRRG( void );

    void convertRG( void );

    void convertRGtoFSM( void );
    void convertLRGtoFSM( void );
    void convertRRGtoFSM( void );

    void convertRGtoRE( void );
    void convertLRGtoRE( void );
    void convertRRGtoRE( void );

    void convertRGtoRG( void );
    void convertLRGtoRRG( void );
    void convertRRGtoLRG( void );

    std::list<sax::Token> & m_tokens;
    TFormalism m_source, m_target;
    TAlgorithm m_algorithm;
    std::ostream & m_out;
};

} /* namespace conversions */

#endif /* ALGORITHMCHOOSER_H_ */