#ifndef _CLI_OPERATOR_INTROSPECTION_COMMAND_H_
#define _CLI_OPERATOR_INTROSPECTION_COMMAND_H_

#include <ast/Command.h>
#include <environment/Environment.h>

namespace cli {

class OperatorsIntrospectionCommand : public Command {
	static void typePrint ( const ext::pair < std::string, abstraction::TypeQualifiers::TypeQualifierSet > & result, std::ostream & os ) {
		if ( abstraction::TypeQualifiers::isConst ( std::get < 1 > ( result ) ) )
			os << "const ";

		os << std::get < 0 > ( result );

		if ( abstraction::TypeQualifiers::isLvalueRef ( std::get < 1 > ( result ) ) )
			os << " &";

		if ( abstraction::TypeQualifiers::isRvalueRef ( std::get < 1 > ( result ) ) )
			os << " &&";
	}

public:
	OperatorsIntrospectionCommand ( ) {
	}

	template < class Operators >
	static void printOperators ( const ext::list < ext::pair < Operators, abstraction::AlgorithmFullInfo > > & overloads ) {
		for ( const ext::pair < Operators, abstraction::AlgorithmFullInfo > & overload : overloads ) {

			typePrint ( std::get < 1 > ( overload ).getNormalizedResult ( ), common::Streams::out );

			common::Streams::out << " operator ";
			common::Streams::out << abstraction::Operators::toString ( std::get < 0 > ( overload ) );
			common::Streams::out << " (";

			for ( size_t i = 0; i < std::get < 1 > ( overload ).getParams ( ).size ( ); ++ i ) {
				if ( i != 0 )
					common::Streams::out << ",";

				common::Streams::out << " ";

				typePrint ( std::get < 1 > ( overload ).getParams ( ) [ i ], common::Streams::out );

				common::Streams::out << " " << std::get < 1 > ( overload ).getParamNames ( ) [ i ];
			}
			common::Streams::out << " )" << std::endl;
		}
	}

	CommandResult run ( Environment & /* environment */ ) const override {
		printOperators ( abstraction::Registry::listBinaryOperators ( ) );
		printOperators ( abstraction::Registry::listPrefixOperators ( ) );
		printOperators ( abstraction::Registry::listPostfixOperators ( ) );
		return CommandResult::OK;
	}
};

} /* namespace cli */

#endif /* _CLI_OPERATOR_INTROSPECTION_COMMAND_H_ */
