#include <ImageDev/ImageDev.h>
#include <ioformat/IOFormat.h>
#include <iolink/view/ImageViewFactory.h>
#include <iolink/view/ImageViewProvider.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 ( imagedev::isInitialized() == false )
            imagedev::init();

        // Initialize an unsigned 8-bit array storing data of a 2D image
        const uint64_t rowCount = 768;
        const uint64_t colCount = 1024;
        std::vector< uint8_t > imageData( rowCount * colCount );

        // Define a synthetic square in this array
        const uint64_t side = colCount / 2; // side in pixels of the square to draw

        // Loop on image rows
        for ( uint64_t i = 0; i < rowCount; ++i )
        {
            // Loop on image columns
            for ( uint64_t j = 0; j < colCount; ++j )
            {
                if ( ( i >= ( rowCount - side ) / 2 ) && ( i <= ( rowCount + side ) / 2 ) &&
                     ( j >= ( colCount - side ) / 2 ) && ( j <= ( colCount + side ) / 2 ) )
                    imageData[i * colCount + j] = 228; // Value inside the square
                else
                    imageData[i * colCount + j] = 0; // Background value
            }
        }

        // Create an image view of same dimensions
        VectorXu64 imageShape{ colCount, rowCount };
        auto image = ImageViewFactory::allocate( imageShape, DataTypeId::UINT8 );
        image->setAxesInterpretation( ImageTypeId::IMAGE );

        // Define the region where to write the data
        VectorXu64 imageOrig{ 0, 0 };
        RegionXu64 imageRegion( imageOrig, imageShape );

        // Copy the data in the image view
        image->writeRegion( imageRegion, imageData.data() );

        // This image can now be processed by any ImageDev algorithm, for instance for building a color image
        auto imageVoid = resetImage( image, 0.0f );
        auto imageRgb = grayscaleToColor( image, image, imageVoid );

        // Save the created image with IOFormat
        writeView( imageRgb, "T02_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;
}
