/*
 * typeinfo.cpp
 *
 * Created on: Oct 19, 2017
 * Author: Jan Travnicek
 */

#include "typeinfo.hpp"

#include "algorithm.hpp"

namespace ext {

std::string erase_template_info ( std::string str ) {
	std::string::iterator iter = str.begin ( );
	for ( ; ; ) {
		std::pair < std::string::iterator, std::string::iterator > rangeRes = ext::find_range ( iter, str.end ( ), '<', '>' );

		if ( rangeRes.first == rangeRes.second )
			break;

		iter = str.erase ( rangeRes.first, rangeRes.second );
	}
	return str;
}

ext::vector < std::string > get_template_info ( const std::string & str ) {
	ext::vector < std::string > res;
	std::string::const_iterator iter = str.begin ( );
	for ( ; ; ) {
		std::pair < std::string::const_iterator, std::string::const_iterator > rangeRes = ext::find_range ( iter, str.end ( ), '<', '>' );

		if ( rangeRes.first == rangeRes.second )
			break;
		res.push_back ( std::string ( ext::trim ( ext::make_string_view ( rangeRes.first + 1, rangeRes.second - 1 ) ) ) );

		iter = rangeRes.second;
	}

	return res;
}

bool is_same_type ( const std::string & first, const std::string & second ) {
	ext::vector < std::string > explodedFirst = ext::explode ( ext::erase_template_info ( first ), "::" );
	ext::vector < std::string > explodedSecond = ext::explode ( ext::erase_template_info ( second ), "::" );

	if ( explodedFirst.size ( ) > explodedSecond.size ( ) )
		return false;

	size_t offset = explodedSecond.size ( ) - explodedFirst.size ( );

	for ( size_t index = 0; index < explodedFirst.size ( ); ++ index ) {
		if ( explodedFirst [ index ].empty ( ) )
			continue;

		if ( explodedFirst [ index ] != explodedSecond [ index + offset ] )
			return false;
	}

	return true;
}

bool are_same_types ( const std::vector < std::string > & first, const std::vector < std::string > & second ) {
	std::vector < std::string >::const_iterator firstIter = first.begin ( );
	std::vector < std::string >::const_iterator secondIter = second.begin ( );

	while ( firstIter != first.end ( ) && secondIter != second.end ( ) ) {
		if ( ! is_same_type ( * firstIter, * secondIter ) )
			return false;

		++ firstIter;
		++ secondIter;
	}

	return firstIter == first.end ( ) && secondIter == second.end ( );
}

} /* namespace ext */
