/*
 * ValueHolderInterface.hpp
 *
 *  Created on: 11. 7. 2017
 *	  Author: Jan Travnicek
 */

#ifndef _VALUE_HPP_
#define _VALUE_HPP_

#include <memory>
#include <alib/set>
#include <alib/typeindex>

#include <common/ParamQualifiers.hpp>

namespace abstraction {

class OperationAbstraction;

class Value : public std::enable_shared_from_this < Value > {
	std::shared_ptr < abstraction::OperationAbstraction > m_lifeReference;

public:
	Value ( const std::shared_ptr < abstraction::OperationAbstraction > & ref );

	virtual ~Value ( ) noexcept = default;

	virtual std::shared_ptr < abstraction::Value > cloneAsVariable ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool move = false ) = 0;
	virtual std::shared_ptr < abstraction::Value > cloneAsValue ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool move = false ) = 0;

	virtual std::shared_ptr < abstraction::Value > getProxyAbstraction ( );

	virtual ext::type_index getTypeIndex ( ) const = 0;

	std::string getType ( ) const;

	virtual ext::set < abstraction::ParamQualifiers::ParamQualifier > getTypeQualifiers ( ) const = 0;

	const std::shared_ptr < abstraction::OperationAbstraction > & getLifeReference ( ) const;
};

class Void : public Value {
public:
	using Value::Value;

	std::shared_ptr < abstraction::Value > cloneAsVariable ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool move ) override;

	std::shared_ptr < abstraction::Value > cloneAsValue ( bool isConst, bool isRvalueRef, bool isLvalueRef, bool move ) override;

	ext::type_index getTypeIndex ( ) const override;

	ext::set < abstraction::ParamQualifiers::ParamQualifier > getTypeQualifiers ( ) const override;

};

class LazyValue : public Value {
	std::shared_ptr < Value > cache;

public:
	LazyValue ( const std::shared_ptr < abstraction::OperationAbstraction > & ref );

	std::shared_ptr < abstraction::Value > cloneAsVariable ( bool, bool, bool, bool ) override;

	std::shared_ptr < abstraction::Value > cloneAsValue ( bool, bool, bool, bool ) override;

	ext::type_index getTypeIndex ( ) const override;

	ext::set < abstraction::ParamQualifiers::ParamQualifier > getTypeQualifiers ( ) const override;

	std::shared_ptr < abstraction::Value > getProxyAbstraction ( ) override;
};

} /* namespace abstraction */

#endif /* _VALUE_HPP_ */
