/* -*- 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/autotest.hh>
#include <mia/3d/fifotestfixture.hh>
#include <mia/3d/fifof/label.hh>
#include <mia/2d/shape.hh>

NS_MIA_USE;

using namespace std;
using namespace label_2dstack_filter;
namespace bfs =::boost::filesystem;


BOOST_FIXTURE_TEST_CASE( test_fifof_label, fifof_Fixture )
{
       const size_t n_slices = 6;
       const C2DBounds size(4, 4);
       bool input_data[n_slices * 4 * 4] = {
              0, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 1, 0, 0,

              0, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 1, 0, 1,

              1, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 1, 0, 1,

              0, 1, 0, 0,
              0, 0, 0, 0,
              0, 0, 1, 0,
              0, 1, 0, 1,

              0, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 1, 0,
              0, 1, 1, 1,

              0, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 1, 0, 1,

       };
       unsigned int test_data[n_slices * 4 * 4] = {
              0, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 2, 0, 0,

              0, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 2, 0, 3,

              1, 0, 0, 0,
              1, 0, 0, 0,
              0, 0, 0, 0,
              0, 2, 0, 3,

              0, 4, 0, 0,
              0, 0, 0, 0,
              0, 0, 5, 0,
              0, 2, 0, 3,

              0, 0, 0, 0,
              6, 0, 0, 0,
              0, 0, 5, 0,
              0, 5, 5, 5,

              0, 0, 0, 0,
              6, 0, 0, 0,
              0, 0, 0, 0,
              0, 5, 0, 5,

       };
       prepare(input_data, test_data, size, n_slices);
       auto shape = C2DShapePluginHandler::instance().produce("4n");
       C2DLabelStackFilter filter("", shape );
       call_test(filter);
}

class C1n2DShape: public C2DShape
{
public:
       C1n2DShape()
       {
              insert(C2DShape::Flat::value_type( 0, 0));
       }
};


BOOST_AUTO_TEST_CASE( test_labelremap )
{
       CLabelRemapper remap;
       remap.add_pair(1, 2);
       remap.add_pair(2, 3);
       remap.add_pair(3, 4);
       remap.add_pair(13, 7);
       remap.add_pair(13, 1);
       CLabelMap result = remap.get_map();
       BOOST_CHECK_EQUAL(result.size(), 5u);
       BOOST_REQUIRE(result.find(3) != result.end());
       BOOST_REQUIRE(result.find(2) != result.end());
       BOOST_REQUIRE(result.find(4) != result.end());
       BOOST_REQUIRE(result.find(7) != result.end());
       BOOST_REQUIRE(result.find(13) != result.end());
       BOOST_CHECK_EQUAL(result[2], 1);
       BOOST_CHECK_EQUAL(result[3], 1);
       BOOST_CHECK_EQUAL(result[4], 1);
       BOOST_CHECK_EQUAL(result[7], 1);
       BOOST_CHECK_EQUAL(result[13], 1);
}


BOOST_AUTO_TEST_CASE( test_overflow )
{
       const C2DBounds size(40, 40);
       C2DBitImage *img(new C2DBitImage(size));
       fill(img->begin(), img->end(), 1);
       P2DImage pimg(img);
       P2DShape shape(new C1n2DShape());
       C2DLabelStackFilter filter("", shape );
       filter.set_start_label(numeric_limits<unsigned int>::max() - 10);
       typedef TFifoFilterSink<P2DImage> C2DImageFifoFilterSink;
       C2DImageFifoFilterSink::Pointer sink(new C2DImageFifoFilterSink());
       filter.append_filter(sink);
       BOOST_CHECK_THROW(filter.push(pimg), invalid_argument);
}
