/*
 * 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/TypeQualifiers.hpp>

namespace abstraction {

class OperationAbstraction;
class ValueReference;

class Value : public std::enable_shared_from_this < Value > {
protected:
	virtual std::shared_ptr < abstraction::Value > asValue ( bool move, bool isTemporary ) = 0;

public:
	virtual ~Value ( ) noexcept = default;

	std::shared_ptr < abstraction::Value > clone ( abstraction::TypeQualifiers::TypeQualifierSet typeQualifierSet, bool isTemporary );

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

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

	std::string getType ( ) const;

	virtual abstraction::TypeQualifiers::TypeQualifierSet getTypeQualifiers ( ) const = 0;

	virtual bool isTemporary ( ) const = 0;

	friend class ValueReference;
};

class ValueReference : public Value {
	std::weak_ptr < abstraction::Value > m_value;

	abstraction::TypeQualifiers::TypeQualifierSet m_typeQualifiers;
	bool m_isTemporary;

	std::shared_ptr < abstraction::Value > asValue ( bool move, bool isTemporary ) override;

public:
	ValueReference ( std::shared_ptr < abstraction::Value > value, abstraction::TypeQualifiers::TypeQualifierSet typeQualifiers, bool isTemporary );

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

	abstraction::TypeQualifiers::TypeQualifierSet getTypeQualifiers ( ) const override;

	ext::type_index getTypeIndex ( ) const override;

	bool isTemporary ( ) const override;
};

class Void : public Value {
public:
	std::shared_ptr < abstraction::Value > asValue ( bool move, bool isTemporary ) override;

	ext::type_index getTypeIndex ( ) const override;

	abstraction::TypeQualifiers::TypeQualifierSet getTypeQualifiers ( ) const override;

	bool isTemporary ( ) const override;
};

} /* namespace abstraction */

#endif /* _VALUE_HPP_ */
