/*
 * Copyright (c) 2016, 2017 ARM Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifndef ARM_COMPUTE_CL /* Needed by Utils.cpp to handle OpenCL exceptions properly */
#error "This example needs to be built with -DARM_COMPUTE_CL"
#endif /* ARM_COMPUTE_CL */

#include "arm_compute/core/Types.h"
#include "arm_compute/runtime/CL/CLFunctions.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "arm_compute/runtime/NEON/NEFunctions.h"
#include "utils/Utils.h"

using namespace arm_compute;
using namespace utils;

/** Example demonstrating how to use both CL and NEON functions in the same pipeline
 *
 * @param[in] argc Number of arguments
 * @param[in] argv Arguments ( [optional] Path to PPM image to process )
 */
void main_neoncl_scale_median_gaussian(int argc, const char **argv)
{
    /** [NEON / OpenCL Interop] */
    PPMLoader ppm;
    CLImage   src, scale_median, median_gauss, dst;

    CLScheduler::get().default_init();

    if(argc < 2)
    {
        // Print help
        std::cout << "Usage: ./build/cl_convolution [input_image.ppm]\n\n";
        std::cout << "No input_image provided, creating a dummy 640x480 image\n";
        // Create an empty grayscale 640x480 image
        src.allocator()->init(TensorInfo(640, 480, Format::U8));
    }
    else
    {
        ppm.open(argv[1]);
        ppm.init_image(src, Format::U8);
    }

    TensorInfo scale_median_info(TensorInfo(src.info()->dimension(0) / 2, src.info()->dimension(1) / 2, Format::U8));

    // Configure the temporary and destination images
    scale_median.allocator()->init(scale_median_info);
    median_gauss.allocator()->init(scale_median_info);
    dst.allocator()->init(scale_median_info);

    // Declare and configure the functions to create the following pipeline: scale -> median -> gauss
    CLScale       scale;
    NEMedian3x3   median;
    CLGaussian5x5 gauss;

    scale.configure(&src, &scale_median, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::REPLICATE);
    median.configure(&scale_median, &median_gauss, BorderMode::REPLICATE);
    gauss.configure(&median_gauss, &dst, BorderMode::REPLICATE);

    // Allocate all the images
    src.allocator()->allocate();
    scale_median.allocator()->allocate();
    median_gauss.allocator()->allocate();
    dst.allocator()->allocate();

    // Fill the input image with the content of the PPM image if a filename was provided:
    if(ppm.is_open())
    {
        ppm.fill_image(src);
    }

    // Enqueue and flush the OpenCL kernel:
    scale.run();

    // Do a blocking map of the input and output buffers of the NEON function:
    scale_median.map();
    median_gauss.map();

    // Run the NEON function:
    median.run();

    // Unmap the output buffer before it's used again by OpenCL:
    scale_median.unmap();
    median_gauss.unmap();

    // Run the final OpenCL function:
    gauss.run();

    // Make sure all the OpenCL jobs are done executing:
    CLScheduler::get().sync();

    // Save the result to file:
    if(ppm.is_open())
    {
        const std::string output_filename = std::string(argv[1]) + "_out.ppm";
        save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
    }
    /** [NEON / OpenCL Interop] */
}

/** Main program for convolution test
 *
 * @param[in] argc Number of arguments
 * @param[in] argv Arguments ( [optional] Path to PPM image to process )
 */
int main(int argc, const char **argv)
{
    return utils::run_example(argc, argv, main_neoncl_scale_median_gaussian);
}
