#include <catch2/catch.hpp>

#include <alib/iostream>

#include "common/TestLine.hpp"

#include <registry/AlgorithmRegistry.hpp>

TEST_CASE ( "Cli Parser", "[unit][cli]" ) {

	SECTION ( "Test Declare" ) {
		cli::Environment environment;

		testLine ( "declare auto $i = 1", environment );
		testLine ( "print $i", environment );
	}

	SECTION ( "Test Routine1" ) {
		cli::Environment environment;

		testLine ( "function produce1 ( ) returning auto begin return 1; end", environment );
		testLine ( "procedure consume1 ( auto $value ) begin print $value; end", environment );
		testLine ( "execute expression consume1 ( produce1 ( ) )", environment );
	}

	SECTION ( "Test Routine2" ) {
		cli::Environment environment;

		testLine ( "function produce2 ( ) returning auto begin return 1; end", environment );
		testLine ( "procedure consume2 ( auto && $value ) begin print $value; end", environment );
		testLine ( "execute expression consume2 ( produce2 ( ) )", environment );
	}

	SECTION ( "Test Routine3" ) {
		cli::Environment environment;

		testLine ( "procedure consume3 ( auto && $value ) begin print $value; end", environment );
		testLine ( "execute expression consume3 ( 1 + 1 )", environment );
	}

	class Bridge4 {
	public:
		static int && bridge ( int && param ) {
			return std::move ( param );
		}
	};

	SECTION ( "Test Routine4" ) {
		abstraction::AlgorithmRegistry::registerAlgorithm < Bridge4 > ( Bridge4::bridge, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT, std::array < std::string, 1 > ( ) );

		cli::Environment environment;

		testLine ( "function produce4 ( ) returning auto begin return 1; end", environment );
		testLine ( "function bridge4 ( auto && $param ) returning auto && begin return cli::builtin::Move ( $param ); end", environment );
		testLine ( "procedure consume4 ( auto && $value ) begin print $value; end", environment );

		testLine ( "execute expression consume4 ( Bridge4 ( 1 + 1 ) )", environment );
		testLine ( "execute expression consume4 ( Bridge4 ( produce4 ( ) ) )", environment );
		testLine ( "execute expression consume4 ( Bridge4 ( 1 + 1 ) )", environment );
		testLine ( "execute expression consume4 ( Bridge4 ( bridge4 ( produce4 ( ) ) ) )", environment );
		testLine ( "execute expression consume4 ( bridge4 ( Bridge4 ( bridge4 ( produce4 ( ) ) ) ) )", environment );
	}

}
