#ifndef _CLI_ALGORITHMS_INTROSPECTION_COMMAND_H_
#define _CLI_ALGORITHMS_INTROSPECTION_COMMAND_H_

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

namespace cli {

class AlgorithmsIntrospectionCommand : public Command {
	std::unique_ptr < cli::Arg > m_param;

public:
	AlgorithmsIntrospectionCommand ( std::unique_ptr < cli::Arg > param ) : m_param ( std::move ( param ) ) {
	}

	void printAlgos ( const ext::set < ext::pair < std::string, ext::vector < std::string > > > & algos ) const {
		for ( const ext::pair < std::string, ext::vector < std::string > > & algo : algos ) {
			common::Streams::out << algo.first;
			if ( !algo.second.empty ( ) ) {
				common::Streams::out << " @";
				for ( const std::string & templateParam : algo.second )
					common::Streams::out << templateParam;
			}
			common::Streams::out << std::endl;
		}
	}

	Command::Result run ( Environment & environment ) const override {
		std::string param;
		if ( m_param != nullptr )
			param = m_param->eval ( environment );

		if ( param.empty ( ) ) {
			printAlgos ( abstraction::Registry::listAlgorithms ( ) );
		} else if ( param.find ( "::", param.size ( ) - 2 ) != std::string::npos ) {
			printAlgos ( abstraction::Registry::listAlgorithmGroup ( param ) );
		} else {
			throw exception::CommonException ( "Invalid Algorithm introspection param" );
		}
		return Command::Result::OK;
	}
};

} /* namespace cli */

#endif /* _CLI_ALGORITHMS_INTROSPECTION_COMMAND_H_ */
