/* -*- 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.hh>
#include <config.h>


using namespace std;
using namespace mia;

struct PluginTestFixture {

       void test(const set< string >& plugins, const set<string>& test_data) const;
};



BOOST_FIXTURE_TEST_CASE(test_C3DFullCostPluginHandler, PluginTestFixture)
{
       set<string> test_data = { "image", "maskedimage", "taggedssd", "labelimage"};
       test(C3DFullCostPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DImageCostPluginHandler, PluginTestFixture)
{
       set<string> test_data = { "lncc", "ncc", "ngf", "mi", "ssd", "ssd-automask"};
       test(C3DImageCostPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DFilterPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "binarize", "bandpass", "combiner", "convert", "close", "crop", "dilate", "distance", "downscale",
              "erode", "gauss", "gradnorm", "growmask", "invert", "isovoxel", "kmeans",
              "label", "labelmap", "labelscale", "load", "lvdownscale", "mask", "mean", "median", "mlv", "msnormalizer", "open",  "resize", "reorient",
              "sandp", "scale", "selectbig", "sepconv", "sws", "tee", "thinning",
              "transform", "variance", "ws"
       };
       test(C3DFilterPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DImageCombinerPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "absdiff", "add", "sub", "mul", "div"
       };
       test(C3DImageCombinerPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DImageIOPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "analyze",
              "inria",
              "hdf5",
              "mhd",
              "nifti",
              "vff",
              "vti",
              "vtk",
              "dicom",
              "vista",
              "datapool"
       };
       test(C3DImageIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DImageCreatorPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "circle"
       };
       test(C2DImageCreatorPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DImageCreatorPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "lattic", "sphere"
       };
       test(C3DImageCreatorPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DTransformCreatorHandler, PluginTestFixture)
{
       set<string> test_data = {
              "affine", "axisrot", "raffine", "rigid", "spline",
              "translate", "rotation", "rotbend", "vf"
       };
       test(C3DTransformCreatorHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DRegTimeStepPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "direct", "fluid"
       };
       test(C3DRegTimeStepPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DShapePluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "6n", "18n", "26n", "sphere"
       };
       test(C3DShapePluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DVFIOPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "cvista", "vista", "vtk", "datapool"
       };
       test(C3DVFIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DFifoFilterPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "byslice", "gauss", "label", "median", "mlv",
              "dilate", "erode", "open", "close", "regiongrow"
       };
       test(C2DFifoFilterPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DStackDistanceTransformIOPluginHandler, PluginTestFixture)
{
       set<string> test_data {
              "datapool"
       };
       test(C2DStackDistanceTransformIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DTransformationIOPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "datapool", "bbs", "vista", "xml"
       };
       test(C3DTransformationIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C3DRegModelPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "navier", "naviera", "naviersse", "navierpsse"
       };
       test(C3DRegModelPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CMeshIOPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "datapool", "off", "vista", "ply", "stl", "vtk"
       };
       test(CMeshIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CMinimizerPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "gdas", "gsl", "gdsq", "nlopt"
       };
       test(CMinimizerPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CSplineKernelPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "bspline", "omoms"
       };
       test(CSplineKernelPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CNoiseGeneratorPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "gauss", "uniform"
       };
       test(CNoiseGeneratorPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C1DSpacialKernelPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "gauss", "cdiff", "scharr"
       };
       test(C1DSpacialKernelPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DVFIOPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "datapool", "vista", "exr"
       };
       test(C2DVFIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DFullCostPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "image", "labelimage", "maskedimage"
       };
       test(C2DFullCostPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DImageCostPluginHandler, PluginTestFixture)
{
       set<string> test_data =  {
              "lncc", "ncc", "lsd", "ssd", "mi", "ngf", "ssd-automask"
       };
       test(C2DImageCostPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DImageIOPluginHandler, PluginTestFixture)
{
       set<string> test_data =  {
              "bmp", "exr", "datapool", "dicom", "jpg", "png", "raw", "tif", "vista"
       };
       test(C2DImageIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CFFT2DKernelPluginHandler, PluginTestFixture)
{
       set<string> test_data;
       test(CFFT2DKernelPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DShapePluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "4n", "8n", "sphere", "1n", "rectangle", "square"
       };
       test(C2DShapePluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DFilterPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "adaptmed", "admean", "aniso", "bandpass", "binarize", "combiner",
              "convert", "close", "crop", "dilate", "distance",
              "downscale", "erode", "gauss", "gradnorm", "invert", "kmeans",
              "label", "labelmap", "labelscale", "load", "mask", "mean", "meanvar",
              "median", "medianmad", "mlv",
              "ngfnorm", "noise", "open", "pruning", "regiongrow", "sandp",
              "scale", "selectbig", "sepconv", "shmean", "sobel",
              "sort-label", "sws", "tee", "thinning", "thresh", "tmean",
              "transform", "ws"
       };
#ifdef HAVE_MAXFLOW
       test_data.insert("maxflow");
#endif
       test(C2DFilterPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DImageCombinerPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "absdiff", "add", "div", "mul", "sub"
       };
       test(C2DImageCombinerPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DTransformationIOPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "vista", "datapool", "bbs", "xml"
       };
       test(C2DTransformationIOPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_C2DRegModelPluginHandler, PluginTestFixture)
{
       set<string> test_data = {
              "identity", "navier", "naviera"
       };
       test(C2DRegModelPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CCST2DVectorKernelPluginHandler, PluginTestFixture)
{
       set<string> test_data;
       test(CCST2DVectorKernelPluginHandler::instance().get_set(), test_data);
}

BOOST_FIXTURE_TEST_CASE(test_CCST2DImgKernelPluginHandler, PluginTestFixture)
{
       set<string> test_data;
       test(CCST2DImgKernelPluginHandler::instance().get_set(), test_data);
}


BOOST_FIXTURE_TEST_CASE(test_SplineBoundaryConditions, PluginTestFixture)
{
       set<string> test_data = {
              "mirror", "repeat", "zero"
       };
       test(CSplineBoundaryConditionPluginHandler::instance().get_set(), test_data);
}



void PluginTestFixture::test(const set< string >& plugins, const set<string>& test_data) const
{
       BOOST_CHECK_EQUAL(plugins.size(), test_data.size());

       for (auto p = plugins.begin(); p != plugins.end(); ++p) {
              BOOST_CHECK_MESSAGE(test_data.find(*p) != test_data.end(), "unexpected plugin '" << *p << "' found");
       }

       for (auto p = test_data.begin(); p != test_data.end(); ++p)
              BOOST_CHECK_MESSAGE(plugins.find(*p) != plugins.end(), "expected plugin '" << *p << "' not found");
}
