#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 tif file to analyze
        auto imageInput = ioformat::readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "micro_nucleus.tif" );

        // Extract intensity statistics from an RGB image
        std::cout << "Computing color intensity statistics... " << std::endl;
        auto statistics = intensityStatistics( imageInput, IntensityStatistics::RangeMode::MIN_MAX, { 0, 255 } );
        std::cout << "  - Average intensity [R, G, B] = [" << statistics->mean( 0, 0 ) << ", "
                  << statistics->mean( 1, 0 ) << ", " << statistics->mean( 2, 0 ) << "]" << std::endl;
        std::cout << "  - Standard Deviation = [R, G, B] = [" << statistics->standardDeviation( 0, 0 ) << ", "
                  << statistics->standardDeviation( 1, 0 ) << ", " << statistics->standardDeviation( 2, 0 ) << "]"
                  << std::endl;
        std::cout << "  - Red intensity range = [" << statistics->minimum( 0, 0 ) << ", " << statistics->maximum( 0, 0 )
                  << "]" << std::endl;
        std::cout << "  - Green intensity range = [" << statistics->minimum( 1, 0 ) << ", "
                  << statistics->maximum( 1, 0 ) << "]" << std::endl;
        std::cout << "  - Blue intensity range = [" << statistics->minimum( 2, 0 ) << ", "
                  << statistics->maximum( 2, 0 ) << "]" << std::endl;

        // Threshold image pixels having an intensity lower than 190 in each RGB channel
        std::cout << "Color thresholding and binary analysis... " << std::endl;
        auto imageOutput = colorThresholding( imageInput, { 0, 190 }, { 0, 190 }, { 0, 190 } );

        // Measure the object area
        auto area = area2d( imageOutput );
        std::cout << "  - Total area of detected objects = " << area->area( 0 ) << std::endl;
        std::cout << "  - Phase fraction of detected objects = " << ( 100.0 * area->areaFraction( 0 ) ) << " %"
                  << std::endl;

        // Count the number of detected objects
        auto count = objectCount( imageOutput );
        std::cout << "  - Number of detected objects = " << count.outputMeasurement->count( 0 ) << std::endl;
        // Rescale binary the image intensities between 0 and 255 for visualization
        // and save it
        imageOutput = rescaleIntensity( imageOutput,
                                        RescaleIntensity::OutputType::UNSIGNED_INTEGER_8_BIT,
                                        RescaleIntensity::RangeMode::MIN_MAX,
                                        { 2, 98 },
                                        { 0, 255 },
                                        { 0, 255 } );
        ioformat::writeView( imageInput, "T04_01_output.png" );

        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;
}
