/*
 * 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 "expressionserializer.h"
#include <unordered_map>
namespace xreate {

class ContextDomain: private std::vector<Expression>{
	typedef std::vector<Expression> PARENT;

public:
	ContextDomain(const std::vector<Expression>&& expressions);
	ContextDomain(ContextDomain&& other)
		: scheme(std::move(other.scheme)), serializer(std::move(serializer)){}
	boost::optional<size_t> getExpressionId(const Expression& e) const;
	const Expression& get(size_t id) const;
	size_t size() const;
	ContextDomain::const_iterator begin() const;
	ContextDomain::const_iterator end() const;

private:
	ContextDomain(const ContextDomain&)=delete;

	std::map<PackedExpression, size_t> scheme;
	ExpressionSerializer serializer;
};

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

public:
	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 ;

class ContextQuery: public IQuery {
public:
	//AdhocQuery();
	std::list<Expression> getContext(const ScopePacked& scopeId);
	void forceContext(const ScopePacked& scopeId, std::list<Expression> context);
	const ContextDomain& getFunctionDomain(const std::string& name) const;
	const FunctionSpecializations& getFunctionSpecializations(const std::string& name) const;

	virtual void init(ClaspLayer* clasp);
	virtual ~ContextQuery(){};
private:
	std::multimap<ScopePacked, Expression> __modelContext;
	std::multimap<ScopePacked, Expression> __modelForcedContext;
	std::map<std::string, ContextDomain> __modelFunctionContext;
	std::map<std::string, FunctionSpecializations> __modelFunctionSpecializations;

};

} /* namespace xreate */

#endif /* SRC_QUERY_CONTEXT_H_ */
