/*
 * 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>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>

namespace xreate {

typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
typedef boost::bimap<size_t, Expression> FunctionDemand;
typedef std::map<Expression, Expression> Decisions;
typedef std::map<Expression, Expression> DependentDecision;

class ContextQuery: public IQuery {
	//AdhocQuery();
public:
	const Domain& getContext(const ScopePacked& scopeId) const;
	const Domain& getContext(CodeScope* const scope) const;
	void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
	const Domain& getTopicDomain(const Expression& topic) const;
        const DependentDecision& getDependentDecision(ScopePacked scope, const Expression& topic) const;
	const FunctionDemand& getFunctionDemand(const std::string& name) const;
	const Decisions& getFinalDecisions(const ScopePacked& scopeId) const;
        
	virtual void init(ClaspLayer* clasp);
	ContextQuery();
	virtual ~ContextQuery(){};
private:
	ClaspLayer* clasp;
	std::map<ScopePacked, Domain> __modelContext;
	std::map<std::string, FunctionDemand> __modelFunctionDemand;
	std::map<ScopePacked, Decisions> __modelStaticDecisions;
        std::map<Expression, Domain> __modelTopicDomains;
        std::map<ScopePacked, std::map<Expression, DependentDecision>> __modelDependentDecisions;

	void prepareFunctionDemandModel();
        void prepareDecisionModels();
};

} /* 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_ */
