/*
 * Copyright (c) 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.
 */
#define ARM_COMPUTE_CL /* So that OpenCL exceptions get caught too */
#include "arm_compute/core/Types.h"
#include "arm_compute/runtime/CL/CLFunctions.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "utils/Utils.h"

using namespace arm_compute;
using namespace utils;

void main_cl_events(int argc, const char **argv)
{
    /** [OpenCL events] **/
    PPMLoader     ppm;
    CLImage       src, tmp_scale_median, tmp_median_gauss, dst;
    constexpr int scale_factor = 2;

    CLScheduler::get().default_init();

    if(argc < 2)
    {
        // Print help
        std::cout << "Usage: ./build/cl_events [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);
    }

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

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

    // Configure the temporary and destination images
    dst.allocator()->init(dst_info);
    tmp_scale_median.allocator()->init(dst_info);
    tmp_median_gauss.allocator()->init(dst_info);

    //Configure the functions:
    scale.configure(&src, &tmp_scale_median, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::REPLICATE);
    median.configure(&tmp_scale_median, &tmp_median_gauss, BorderMode::REPLICATE);
    gauss.configure(&tmp_median_gauss, &dst, BorderMode::REPLICATE);

    // Allocate all the images
    src.allocator()->allocate();
    dst.allocator()->allocate();
    tmp_scale_median.allocator()->allocate();
    tmp_median_gauss.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 scale OpenCL kernel:
    scale.run();
    // Create a synchronisation event between scale and median:
    cl::Event scale_event = CLScheduler::get().enqueue_sync_event();
    // Enqueue and flush the median OpenCL kernel:
    median.run();
    // Enqueue and flush the Gaussian OpenCL kernel:
    gauss.run();

    //Make sure all the OpenCL jobs are done executing:
    scale_event.wait();        // Block until Scale is done executing (Median3x3 and Gaussian5x5 might still be running)
    CLScheduler::get().sync(); // Block until Gaussian5x5 is done executing

    // 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
    }
    /** [OpenCL events] **/
}

/** 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_cl_events);
}
