/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * context.h
 *
 *  Created on: Dec 1, 2015
 *      Author: pgess <v.melnychenko@xreate.org>
 */

#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{ namespace context{

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

/** \brief Extracts logic solver's solutions about Context */
class ContextQuery: public IQuery {
	//AdhocQuery();
public:
        /**\brief Returns scope's context */
	const Domain& getContext(const ScopePacked& scopeId) const;
        /**\brief Returns scope's context */
	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::context */

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