#pragma once

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

#include <global/GlobalData.h>
#include <registry/Registry.h>

namespace cli {

class PrintCommand : public Command {
	std::unique_ptr < Expression > m_expr;

public:
	PrintCommand ( std::unique_ptr < Expression > expr ) : m_expr ( std::move ( expr ) ) {
	}

	CommandResult run ( Environment & environment ) const override {
		std::shared_ptr < abstraction::Value > value = m_expr->translateAndEval ( environment );

		if ( value->getType ( ) == std::string ( ext::to_string < void > ( ) ) )
			throw std::invalid_argument ( "Printing void is not allowed." );

		std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getValuePrinterAbstraction ( value->getType ( ) );

		res->attachInput ( value, 0 );
		res->attachInput ( std::make_shared < abstraction::ValueHolder < std::ostream & > > ( common::Streams::out, false ), 1 );
		std::shared_ptr < abstraction::Value > result = res->eval ( );
		if ( ! result )
			throw std::invalid_argument ( "Eval of result print statement failed." );

		return CommandResult::OK;
	}
};

} /* namespace cli */

