#ifndef _CLI_WHILE_COMMAND_H_
#define _CLI_WHILE_COMMAND_H_

#include <ast/Command.h>
#include <environment/Environment.h>
#include <ast/Statement.h>
#include <common/CastHelper.h>

namespace cli {

class WhileCommand : public Command {
	std::unique_ptr < Expression > m_condition;
	std::unique_ptr < Command > m_body;

public:
	WhileCommand ( std::unique_ptr < Expression > condition, std::unique_ptr < Command > body ) : m_condition ( std::move ( condition ) ), m_body ( std::move ( body ) ) {
	}

	CommandResult run ( Environment & environment ) const override {
		CommandResult res = cli::CommandResult::OK;
		while ( res == cli::CommandResult::OK ) {
			std::shared_ptr < abstraction::Value > conditionResult = m_condition->translateAndEval ( environment );

			std::shared_ptr < abstraction::Value > castedResult = abstraction::CastHelper::eval ( environment, conditionResult, "bool" );

			if ( ! std::static_pointer_cast < abstraction::ValueHolderInterface < bool > > ( castedResult )->getValue ( ) )
				break;

			res = m_body->run ( environment );

			if ( res == CommandResult::CONTINUE )
				res = CommandResult::OK;

			if ( res == CommandResult::BREAK ) {
				res = CommandResult::OK;
				break;
			}
		}

		return res;
	}
};

} /* namespace cli */

#endif /* _CLI_WHILE_COMMAND_H_ */
