/*
 * DiffAux.h
 *
 *  Created on: Apr 1, 2013
 *      Author: honza
 */

#ifndef _DIFF_AUX_H_
#define _DIFF_AUX_H_

#include <alib/set>
#include <alib/list>
#include <alib/map>
#include <alib/multimap>
#include <alib/vector>
#include <alib/algorithm>

namespace compare {

class DiffAux {
public:
	template < class T >
	static void setDiff ( std::ostream & out, const ext::set < T > & a, const ext::set < T > & b );
	template < class T >
	static void vectorDiff ( std::ostream & out, const ext::vector < T > & a, const ext::vector < T > & b );
	template < class T >
	static void listDiff ( std::ostream & out, const ext::list < T > & a, const ext::list < T > & b );
	template < class T, class R >
	static void mapDiff ( std::ostream & out, const ext::map < T, R > & a, const ext::map < T, R > & b );
	template < class T, class R >
	static void mapDiff ( std::ostream & out, const ext::multimap < T, R > & a, const ext::multimap < T, R > & b );
};

template <class T>
void DiffAux::setDiff(std::ostream & out, const ext::set<T> &a, const ext::set<T> &b) {
	ext::set<T> aMinusB;
	std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(aMinusB, aMinusB.begin()));

	ext::set<T> bMinusA;
	std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::inserter(bMinusA, bMinusA.begin()));

	for(typename ext::set<T>::const_iterator iter = aMinusB.begin(); iter != aMinusB.end(); iter++)
		out << "< " << *iter << std::endl;

	out << "---" << std::endl;

	for(typename ext::set<T>::const_iterator iter = bMinusA.begin(); iter != bMinusA.end(); iter++)
		out << "> " << *iter << std::endl;
}

template < class T >
void DiffAux::vectorDiff (std::ostream & out,  const ext::vector < T > & a, const ext::vector < T > & b ) {
	ext::vector < T > aMinusB;
	std::set_difference ( a.begin ( ), a.end ( ), b.begin ( ), b.end ( ), std::inserter ( aMinusB, aMinusB.begin ( ) ) );

	ext::vector < T > bMinusA;
	std::set_difference ( b.begin ( ), b.end ( ), a.begin ( ), a.end ( ), std::inserter ( bMinusA, bMinusA.begin ( ) ) );

	for ( typename ext::vector < T >::const_iterator iter = aMinusB.begin ( ); iter != aMinusB.end ( ); iter++ )
		out << "< " << * iter << std::endl;

	out << "---" << std::endl;

	for ( typename ext::vector < T >::const_iterator iter = bMinusA.begin ( ); iter != bMinusA.end ( ); iter++ )
		out << "> " << * iter << std::endl;
}

template <class T>
void DiffAux::listDiff(std::ostream & out, const ext::list<T> &a, const ext::list<T> &b) {
	ext::list<T> aMinusB;
	std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(aMinusB, aMinusB.begin()));

	ext::list<T> bMinusA;
	std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::inserter(bMinusA, bMinusA.begin()));

	for(typename ext::list<T>::const_iterator iter = aMinusB.begin(); iter != aMinusB.end(); iter++)
		out << "< " << *iter << std::endl;

	out << "---" << std::endl;

	for(typename ext::list<T>::const_iterator iter = bMinusA.begin(); iter != bMinusA.end(); iter++)
		out << "> " << *iter << std::endl;
}

template <class T, class R>
void DiffAux::mapDiff(std::ostream & out, const ext::map<T, R> &a, const ext::map<T, R> &b) {
	ext::map<T, R> aMinusB;
	std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(aMinusB, aMinusB.begin()));

	ext::map<T, R> bMinusA;
	std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::inserter(bMinusA, bMinusA.begin()));

	for(typename ext::map<T, R>::const_iterator iter = aMinusB.begin(); iter != aMinusB.end(); iter++)
		out << "< " << iter->first << ", " << iter->second << std::endl;

	out << "---" << std::endl;

	for(typename ext::map<T, R>::const_iterator iter = bMinusA.begin(); iter != bMinusA.end(); iter++)
		out << "> " << iter->first << ", " << iter->second << std::endl;
}

template <class T, class R>
void DiffAux::mapDiff(std::ostream & out, const ext::multimap<T, R> &a, const ext::multimap<T, R> &b) {
	ext::map<T, R> aMinusB;
	std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(aMinusB, aMinusB.begin()));

	ext::map<T, R> bMinusA;
	std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::inserter(bMinusA, bMinusA.begin()));

	for(typename ext::map<T, R>::const_iterator iter = aMinusB.begin(); iter != aMinusB.end(); iter++)
		out << "< " << iter->first << ", " << iter->second << std::endl;

	out << "---" << std::endl;

	for(typename ext::map<T, R>::const_iterator iter = bMinusA.begin(); iter != bMinusA.end(); iter++)
		out << "> " << iter->first << ", " << iter->second << std::endl;
}

} /* namespace compare */

#endif /* _DIFF_AUX_H_ */
