#include <ImageDev/ImageDev.h>
#include <ioformat/IOFormat.h>
#include <string.h>

using namespace imagedev;
using namespace ioformat;
using namespace iolink;

int
main( int argc, char* argv[] )
{
    int status = 0;

    try
    {
        // ImageDev library initialization
        if ( isInitialized() == false )
            imagedev::init();

        // Open a 3D Amira Mesh file
        auto imageInput = ioformat::readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "shale.am" );

        // Callback that displays the progression percentage
        auto progressionCallback = []( const GenericAlgorithm& algorithm, float ratio ) {
            std::cout << " - Progression: " << 100.0 * ratio << "%" << std::endl;
        };

        // Callback that displays the algorithm information
        auto informationCallback = []( const GenericAlgorithm& algorithm, const std::string& message ) {
            std::cout << " - Information: " << message << std::endl;
        };

        // Enable a callback for indicating the algorithm progression
        setProgressRatioCallback( progressionCallback );

        // Apply a closing filter
        auto imageOutput = closing3d( imageInput, 50, Closing3d::CONNECTIVITY_26, Closing3d::LIMITED );

        // Disable the progression callback
        setProgressRatioCallback( nullptr );

        // Enable a callback for indicating the algorithm information
        setProgressMessageCallback( informationCallback );

        // Apply a closing by reconstruction filter
        imageOutput = closingByReconstruction3d( imageInput, 20, ClosingByReconstruction3d::CONNECTIVITY_26 );

        // Disable the information callback
        setProgressMessageCallback( nullptr );

        // Enable the verbose mode that indicates the duration of each algorithm
        setVerbose( true );

        // Apply a median filter
        imageOutput = medianFilter3d( imageInput, 5, MedianFilter3d::CUBE, MedianFilter3d::AUTOMATIC );

        // Disable the verbose mode
        setVerbose( false );

        std::cout << "This example ran successfully." << std::endl;
    }
    catch ( const imagedev::Exception& error )
    {
        // Print potential exception in the standard output
        std::cerr << "ImageDev exception: " << error.what() << std::endl;
        status = -1;
    }

    // ImageDev library finalization
    imagedev::finish();

    // Check if we must ask for an enter key to close the program
    if ( !( ( argc == 2 ) && strcmp( argv[1], "--no-stop-at-end" ) == 0 ) )
        std::cout << "Press Enter key to close this window." << std::endl, getchar();

    return status;
}
