/*
 * expressionserializer.h
 *
 *  Created on: Jan 4, 2016
 *      Author: pgess
 */

#ifndef SRC_EXPRESSIONSERIALIZER_H_
#define SRC_EXPRESSIONSERIALIZER_H_

#include "ast.h"
#include <string>
#include <boost/optional.hpp>

namespace xreate {

struct PackedExpression{
	PackedExpression(){};
	PackedExpression(PackedExpression&& other);
	~PackedExpression();
	void operator<< (const std::pair<size_t, size_t>& value);
	char* operator*(){return __storage;}
	bool operator==(const PackedExpression& other) const;
	bool operator!=(const PackedExpression& other) const;
	bool operator<(const PackedExpression& other) const;
	private:
		PackedExpression (const PackedExpression&)=delete;
		PackedExpression& operator=(const PackedExpression&)=delete;
		PackedExpression& operator=(PackedExpression&&)=delete;

		char* __storage = nullptr;
		size_t size =0;
		unsigned char countRemainedBits =0;
};
typedef boost::optional<PackedExpression> OptionalPackedExpression;

class ExpressionSerializerPrivate;

class ExpressionSerializer {
public:
	template<class Container>
	ExpressionSerializer(const Container& source): ExpressionSerializer(){
		for (const Expression& e: source) {
			registerExpression(e);
		}
	}

	template<class Container, class Transformer>
	ExpressionSerializer(const Container& source, Transformer op): ExpressionSerializer(){
		for (const typename Container::value_type& e: source) {
			registerExpression(op(e));
		}
	}

	ExpressionSerializer(ExpressionSerializer&& other)
		: strategy(other.strategy)	{other.strategy = 0; }

	virtual ~ExpressionSerializer();

	PackedExpression getId(const Expression& e);
	OptionalPackedExpression getIdOptional(const Expression& e) const;

private:
	ExpressionSerializerPrivate* strategy;

	void registerExpression(const Expression&e);
	ExpressionSerializer();
};

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

public:
        ExpressionSerializerIntegral();
	ExpressionSerializerIntegral(const std::vector<Expression>&& expressions);
        
	template<class Iterator>
	ExpressionSerializerIntegral(Iterator first, Iterator last)
		: ExpressionSerializerIntegral(std::vector<Expression>(first, last)){}

	ExpressionSerializerIntegral(ExpressionSerializerIntegral&& other)
		: PARENT(std::move(other)), __registry(std::move(other.__registry)), serializer(std::move(other.serializer)){}
        
	size_t getId(const Expression& e) const;
	boost::optional<size_t> getIdOptional(const Expression& e) const;
	const Expression& get(size_t id) const;
	size_t size() const;
	size_t count(const Expression& e) const;
	ExpressionSerializerIntegral::const_iterator begin() const;
	ExpressionSerializerIntegral::const_iterator end() const;

private:
	ExpressionSerializerIntegral(const ExpressionSerializerIntegral&)=delete;

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



} /* namespace xreate */

#endif /* SRC_EXPRESSIONSERIALIZER_H_ */
