/* -*- mia-c++  -*-
 *
 * This file is part of MIA - a toolbox for medical image analysis 
 * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
 *
 * MIA is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MIA; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <type_traits>

#include <mia/core/attributes.hh>
#include <mia/test/testhelpers.hh>

#ifndef mia_template_filtertest_hh
#define mia_template_filtertest_hh

NS_MIA_BEGIN

/**
   @ingroup test 
   @brief a Fixture to do general plug.in testing 

   This filter test class runs given filter and tests whether the 
   expected result is obtained and a test attribute is passed on. 
*/
template <template <class> class Image> 
class TFiltertestFixture {
	typedef typename Image<int>::dimsize_type dimsize_type; 
public: 
	
	TFiltertestFixture():m_attr(new CStringAttribute("teststring")) 
	{
	}

	/**
	   @tparam the filter to test 
	   @tparam the input pixel type 
	   @tparam the expected output pixel type 
	   @param in_size  size of the input image 
	   @param init_data input data array 
	   @param out_size size of the expected output image 
	   @param test_data expected data 
	   @param f filter to run 
	*/
	template <typename Filter, typename IN, typename OUT> 
	void run(const dimsize_type& in_size, const IN *init_data, 
		 const dimsize_type& out_size, const OUT *test_data, const Filter& f) {
		Image<IN> image(in_size, init_data); 
		image.set_attribute("test_attr", m_attr); 
		
		auto result = f.filter(image); 
		
		// test attribute transfer 
		auto result_attr = result->get_attribute("test_attr"); 
		BOOST_REQUIRE(result_attr); 
		BOOST_CHECK_EQUAL(*result_attr, *m_attr); 


		// test output data 
		auto r =  dynamic_cast<const Image<OUT>&>(*result);

		BOOST_CHECK_EQUAL(r.get_size(), out_size); 
		BOOST_REQUIRE(r.get_size()== out_size); 
		
		const OUT *t = test_data; 
		auto i = r.begin_range(dimsize_type::_0, out_size); 
		auto e = r.end_range(dimsize_type::_0, out_size); 
		while (i != e) {
			if (*i !=  *t) 
				cvfail() << i.pos() << "\n"; 
			miatest::equal_or_close(*i, *t);
			++i; ++t; 
		}
	}
private: 
	PAttribute m_attr; 
}; 

NS_MIA_END

#endif
