/*
 * adhoc.h
 *
 *  Created on: Dec 1, 2015
 *      Author: pgess
 */

#ifndef SRC_QUERY_CONTEXT_H_
#define SRC_QUERY_CONTEXT_H_

#include "clasplayer.h"
#include "ast.h"
#include "serialization.h"
#include <unordered_map>

#include <boost/bimap.hpp>
namespace xreate {

typedef ExpressionSerialization<RequirementIntegralCode>::Serializer ContextDomain;
typedef boost::bimap<size_t, std::string> FunctionContextDemand;
typedef std::map<std::string, Expression> ScopeContextDecisions;

class ContextQuery: public IQuery {
public:
	//AdhocQuery();
	const ContextDomain& getContext(const ScopePacked& scopeId);
	const ContextDomain& getContext(CodeScope* const scope);
	void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
	const ContextDomain& getFunctionDomain(const std::string& name) const;
	const FunctionContextDemand& getFunctionDemand(const std::string& name) const;
	const ScopeContextDecisions& getStaticDecisions(const ScopePacked& scopeId);
	virtual void init(ClaspLayer* clasp);
	ContextQuery();
	virtual ~ContextQuery(){};
private:
	ClaspLayer* clasp;
	std::map<ScopePacked, ContextDomain> __modelContext;
	std::map<std::string, ContextDomain> __modelFunctionDomain;
	std::map<std::string, FunctionContextDemand> __modelFunctionDemand;
	std::map<ScopePacked, ScopeContextDecisions> __modelStaticDecisions;

	const ContextDomain domainEmpty;
	const FunctionContextDemand decisionsEmpty;
	const ScopeContextDecisions contextDecisionsEmpty;

	void prepareDemandModel();
};

} /* namespace xreate */

/*
template <typename ATTACHMENTS>
class ContextAttachments: private std::unordered_map<size_t, ATTACHMENTS> {
	typedef std::unordered_map<size_t, ATTACHMENTS> PARENT;

public:
	ContextAttachments(ContextAttachments&& other)
		: PARENT(std::move(other)), domain(std::move(other.domain)) {}

	ContextAttachments(std::vector<Expression>&& expressions, std::vector<ATTACHMENTS>&& attachments)
			: domain(move(expressions))
	{
		size_t size = domain.size();
		for (size_t i=0; i<size; ++i){
			PARENT::emplace(i, std::move(attachments[i]));
		}
	}

	size_t size() const {
		return PARENT::size();
	}

	size_t count(const Expression& e) const {
		return (domain.getExpressionId(e)? 1: 0);
	}

	const ATTACHMENTS& at(const Expression& e) const{
		auto id = domain.getExpressionId(e);
		assert(id);
		return PARENT::at(*id);
	}

private:
	ContextDomain domain;
};
typedef ContextAttachments<ManagedFnPtr> FunctionSpecializations ;
*/

#endif /* SRC_QUERY_CONTEXT_H_ */
