/*
 * Copyright (c) 2018-2021 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.
 */
#include "arm_compute/graph.h"
#include "support/ToolchainSupport.h"
#include "utils/CommonGraphOptions.h"
#include "utils/GraphUtils.h"
#include "utils/Utils.h"

using namespace arm_compute;
using namespace arm_compute::utils;
using namespace arm_compute::graph::frontend;
using namespace arm_compute::graph_utils;

/** Example demonstrating how to implement VGG based VDSR network using the Compute Library's graph API */
class GraphVDSRExample : public Example
{
public:
    GraphVDSRExample()
        : cmd_parser(), common_opts(cmd_parser), common_params(), graph(0, "VDSR")
    {
        model_input_width  = cmd_parser.add_option<SimpleOption<unsigned int>>("image-width", 192);
        model_input_height = cmd_parser.add_option<SimpleOption<unsigned int>>("image-height", 192);

        // Add model id option
        model_input_width->set_help("Input image width.");
        model_input_height->set_help("Input image height.");
    }
    GraphVDSRExample(const GraphVDSRExample &) = delete;
    GraphVDSRExample &operator=(const GraphVDSRExample &) = delete;
    ~GraphVDSRExample() override                          = default;
    bool do_setup(int argc, char **argv) override
    {
        // Parse arguments
        cmd_parser.parse(argc, argv);
        cmd_parser.validate();

        // Consume common parameters
        common_params = consume_common_graph_parameters(common_opts);

        // Return when help menu is requested
        if(common_params.help)
        {
            cmd_parser.print_help(argv[0]);
            return false;
        }

        // Get input image width and height
        const unsigned int image_width  = model_input_width->value();
        const unsigned int image_height = model_input_height->value();

        // Print parameter values
        std::cout << common_params << std::endl;
        std::cout << "Image width: " << image_width << std::endl;
        std::cout << "Image height: " << image_height << std::endl;

        // Get trainable parameters data path
        const std::string data_path  = common_params.data_path;
        const std::string model_path = "/cnn_data/vdsr_model/";

        // Create a preprocessor object
        std::unique_ptr<IPreprocessor> preprocessor = std::make_unique<TFPreproccessor>();

        // Create input descriptor
        const TensorShape tensor_shape     = permute_shape(TensorShape(image_width, image_height, 1U, common_params.batches), DataLayout::NCHW, common_params.data_layout);
        TensorDescriptor  input_descriptor = TensorDescriptor(tensor_shape, common_params.data_type).set_layout(common_params.data_layout);

        // Set weights trained layout
        const DataLayout weights_layout = DataLayout::NCHW;

        // Note: Quantization info are random and used only for benchmarking purposes
        graph << common_params.target
              << common_params.fast_math_hint
              << InputLayer(input_descriptor.set_quantization_info(QuantizationInfo(0.0078125f, 128)),
                            get_input_accessor(common_params, std::move(preprocessor), false));

        SubStream left(graph);
        SubStream right(graph);

        // Layer 1
        right << ConvolutionLayer(
                  3U, 3U, 64U,
                  get_weights_accessor(data_path, "conv0_w.npy", weights_layout),
                  get_weights_accessor(data_path, "conv0_b.npy"),
                  PadStrideInfo(1, 1, 1, 1), 1, QuantizationInfo(0.031778190285f, 156), QuantizationInfo(0.0784313753247f, 128))
              .set_name("conv0")
              << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name("conv0/Relu");

        // Rest 17 layers
        for(unsigned int i = 1; i < 19; ++i)
        {
            const std::string conv_w_path = "conv" + arm_compute::support::cpp11::to_string(i) + "_w.npy";
            const std::string conv_b_path = "conv" + arm_compute::support::cpp11::to_string(i) + "_b.npy";
            const std::string conv_name   = "conv" + arm_compute::support::cpp11::to_string(i);
            right << ConvolutionLayer(
                      3U, 3U, 64U,
                      get_weights_accessor(data_path, conv_w_path, weights_layout),
                      get_weights_accessor(data_path, conv_b_path),
                      PadStrideInfo(1, 1, 1, 1), 1, QuantizationInfo(0.015851572156f, 93))
                  .set_name(conv_name)
                  << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name(conv_name + "/Relu");
        }

        // Final layer
        right << ConvolutionLayer(
                  3U, 3U, 1U,
                  get_weights_accessor(data_path, "conv20_w.npy", weights_layout),
                  get_weights_accessor(data_path, "conv20_b.npy"),
                  PadStrideInfo(1, 1, 1, 1), 1, QuantizationInfo(0.015851572156f, 93))
              .set_name("conv20")
              << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name("conv20/Relu");

        // Add residual to input
        graph << EltwiseLayer(std::move(left), std::move(right), EltwiseOperation::Add).set_name("add")
              << OutputLayer(std::make_unique<DummyAccessor>(0));

        // Finalize graph
        GraphConfig config;
        config.num_threads        = common_params.threads;
        config.use_tuner          = common_params.enable_tuner;
        config.tuner_mode         = common_params.tuner_mode;
        config.tuner_file         = common_params.tuner_file;
        config.mlgo_file          = common_params.mlgo_file;
        config.use_synthetic_type = arm_compute::is_data_type_quantized(common_params.data_type);
        config.synthetic_type     = common_params.data_type;

        graph.finalize(common_params.target, config);

        return true;
    }
    void do_run() override
    {
        // Run graph
        graph.run();
    }

private:
    CommandLineParser           cmd_parser;
    CommonGraphOptions          common_opts;
    SimpleOption<unsigned int> *model_input_width{ nullptr };
    SimpleOption<unsigned int> *model_input_height{ nullptr };
    CommonGraphParams           common_params;
    Stream                      graph;
};

/** Main program for VGG-based VDSR
 *
 * Model is based on:
 *      https://arxiv.org/pdf/1511.04587.pdf
 *      "Accurate Image Super-Resolution Using Very Deep Convolutional Networks"
 *      Jiwon Kim, Jung Kwon Lee and Kyoung Mu Lee
 *
 * @note To list all the possible arguments execute the binary appended with the --help option
 *
 * @param[in] argc Number of arguments
 * @param[in] argv Arguments
 */
int main(int argc, char **argv)
{
    return arm_compute::utils::run_example<GraphVDSRExample>(argc, argv);
}
