/* -*- 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 <mia/internal/plugintester.hh>
#include <mia/2d/imageio.hh>

#include <addons/maxflow/2dmaxflow.hh>

using namespace std;
using namespace mia;
using maxflow_2dimage_filter::C2DMaxflowFilterPluginFactory;

BOOST_AUTO_TEST_CASE ( test_2d_simple_maxflow )
{
// one source, one sink and a pretty simple 4x4 image
       // sink and source
       vector<unsigned char> image = {
              255, 255, 245, 233,
              200, 170, 170, 150,
              20,   30,  40,  30,
              40,   20,  50,  10
       };
       vector<bool> expect = {
              false, false, false, false,
              false, false, false, false,
              true, true, true, true,
              true, true, true, true
       };
       C2DBounds sink(0, 0);
       C2DBounds source(3, 3);
       C2DBounds size(4, 4);
       C2DUBImage in_image(size, image);
       // define a flow image
       // max flow = 1
       // min flow = 0
       C2DFImage *fimage = new C2DFImage(size);
       (*fimage)(sink) = 16.0f;
       P2DImage sink_image(fimage);
       fimage = new C2DFImage(size);
       (*fimage)(source) = 16.0f;
       P2DImage source_image(fimage);
       auto maxflow = BOOST_TEST_create_from_plugin<C2DMaxflowFilterPluginFactory>("maxflow:source-flow=src.@,sink-flow=sink.@");
       save_image("src.@", source_image);
       save_image("sink.@", sink_image);
       auto result = maxflow->filter( in_image );
       BOOST_REQUIRE(result);
       BOOST_CHECK_EQUAL ( result->get_size(), size);
       BOOST_CHECK_EQUAL ( result->get_pixel_type(), it_bit);
       auto& bit_result = dynamic_cast<const C2DBitImage&>(*result);
       auto iexp = expect.begin();

       for (auto ires = bit_result.begin(); ires != bit_result.end(); ++ires, ++iexp) {
              BOOST_CHECK_EQUAL(*ires, *iexp);
       }
}


BOOST_AUTO_TEST_CASE( test_throw_missing_or_wrong_parameter )
{
       C2DUBImage in_image(C2DBounds(4, 4));
       save_image("test.@", in_image);
       BOOST_CHECK_THROW(BOOST_TEST_create_from_plugin<C2DMaxflowFilterPluginFactory>("maxflow"),
                         invalid_argument);
       BOOST_CHECK_THROW(BOOST_TEST_create_from_plugin<C2DMaxflowFilterPluginFactory>("maxflow:sink-flow=test.@"),
                         invalid_argument);
       BOOST_CHECK_THROW(BOOST_TEST_create_from_plugin<C2DMaxflowFilterPluginFactory>("maxflow:source-flow=test.@"),
                         invalid_argument);
       auto maxflow = BOOST_TEST_create_from_plugin<C2DMaxflowFilterPluginFactory>("maxflow:source-flow=test.@,sink-flow=test.@");
       // should throw because we don't accept non-float flow images
       BOOST_CHECK_THROW(maxflow->filter(in_image), invalid_argument);
}

BOOST_AUTO_TEST_CASE( test_throw_wrong_sizes )
{
       C2DFImage flow_image(C2DBounds(4, 4));
       save_image("test.@", flow_image);
       C2DFImage wrong_image_size(C2DBounds(4, 5));
       wrong_image_size(0, 0) = 1.0;
       auto maxflow = BOOST_TEST_create_from_plugin<C2DMaxflowFilterPluginFactory>("maxflow:source-flow=test.@,sink-flow=test.@");
       BOOST_CHECK_THROW(maxflow->filter(wrong_image_size), invalid_argument);
       C2DFImage flat_image(C2DBounds(4, 4));
       BOOST_CHECK_THROW(maxflow->filter(flat_image), invalid_argument);
}

