/*
 * AnyaryOperationAbstraction.hpp
 *
 *  Created on: 20. 8. 2017
 *	  Author: Jan Travnicek
 */

#ifndef _ANYARY_OPERATION_ABSTRACTION_HPP_
#define _ANYARY_OPERATION_ABSTRACTION_HPP_

#include <alib/memory>

#include <abstraction/OperationAbstraction.hpp>
#include <common/AbstractionHelpers.hpp>

namespace abstraction {

class AnyaryOperationAbstractionImpl : virtual public OperationAbstraction {
	ext::vector < std::pair < std::shared_ptr < abstraction::Value >, bool > > m_params;

protected:
	ext::vector < std::pair < std::shared_ptr < abstraction::Value >, bool > > & getParams ( ) {
		return m_params;
	}

	virtual std::shared_ptr < abstraction::Value > run ( ) = 0;

private:
	void attachInput ( const std::shared_ptr < abstraction::Value > & input, size_t index, bool move ) override;

	void detachInput ( size_t index ) override;

public:
	AnyaryOperationAbstractionImpl ( ) = default;

	bool inputsAttached ( ) const override;

	std::shared_ptr < abstraction::Value > eval ( ) override;

	size_t numberOfParams ( ) const override {
		return m_params.size ( );
	}

};

template < class ParamType >
class AnyaryOperationAbstraction : virtual public AnyaryOperationAbstractionImpl {
public:
	ext::type_index getParamTypeIndex ( size_t ) const override {
		return ext::type_index ( typeid ( ParamType ) );
	}

	ext::set < abstraction::ParamQualifiers::ParamQualifier > getParamTypeQualifiers ( size_t ) const override {
		return abstraction::ParamQualifiers::paramQualifiers < ParamType > ( );
	}

};

} /* namespace abstraction */

#endif /* _ANYARY_OPERATION_ABSTRACTION_HPP_ */
