/*
 * Copyright (c) 2022 Arm Limited. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "log_macros.h"
#include "ImageUtils.hpp"
#include "YoloFastestModel.hpp"
#include "TensorFlowLiteMicro.hpp"
#include "DetectorPostProcessing.hpp"
#include "InputFiles.hpp"
#include "UseCaseCommonUtils.hpp"

#include <catch.hpp>

void GetExpectedResults(std::vector<std::vector<arm::app::object_detection::DetectionResult>> &expected_results)
{
    /* Img1
    0)  (0.999246) -> Detection box: {x=89,y=17,w=41,h=56}
    1)  (0.995367) -> Detection box: {x=27,y=81,w=48,h=53}
    */
    expected_results.push_back({
        arm::app::object_detection::DetectionResult(0.99,89,17,41,56),
        arm::app::object_detection::DetectionResult(0.99,27,81,48,53)
    });
    /* Img2
    0)  (0.998107) -> Detection box: {x=87,y=35,w=53,h=64}
    */
    expected_results.push_back({
        arm::app::object_detection::DetectionResult(0.99,87,35,53,64)
    });
    /* Img3
    0)  (0.999244) -> Detection box: {x=105,y=73,w=58,h=66}
    1)  (0.985984) -> Detection box: {x=34,y=40,w=70,h=95}
    */
    expected_results.push_back({
        arm::app::object_detection::DetectionResult(0.99,105,73,58,66),
        arm::app::object_detection::DetectionResult(0.98,34,40,70,95)
    });
    /* Img4
    0)  (0.993294) -> Detection box: {x=22,y=43,w=39,h=53}
    1)  (0.992021) -> Detection box: {x=63,y=60,w=38,h=45}
    */
    expected_results.push_back({
        arm::app::object_detection::DetectionResult(0.99,22,43,39,53),
        arm::app::object_detection::DetectionResult(0.99,63,60,38,45)
    });
}

bool RunInference(arm::app::Model& model, const uint8_t imageData[])
{
    TfLiteTensor* inputTensor = model.GetInputTensor(0);
    REQUIRE(inputTensor);

    const size_t copySz = inputTensor->bytes < IMAGE_DATA_SIZE ?
                            inputTensor->bytes : IMAGE_DATA_SIZE;

    arm::app::image::RgbToGrayscale(imageData,inputTensor->data.uint8,copySz);

    if(model.IsDataSigned()){
        arm::app::image::ConvertImgToInt8(inputTensor->data.data, copySz);
    }

    return model.RunInference();
}

template<typename T>
void TestInferenceDetectionResults(int imageIdx, arm::app::Model& model, T tolerance) {

    std::vector<arm::app::object_detection::DetectionResult> results;
    auto image = get_img_array(imageIdx);

    TfLiteIntArray* inputShape = model.GetInputShape(0);
    auto nCols = inputShape->data[arm::app::YoloFastestModel::ms_inputColsIdx];
    auto nRows = inputShape->data[arm::app::YoloFastestModel::ms_inputRowsIdx];

    REQUIRE(RunInference(model, image));


    std::vector<TfLiteTensor*> output_arr{model.GetOutputTensor(0), model.GetOutputTensor(1)};
    for (size_t i =0; i < output_arr.size(); i++) {
        REQUIRE(output_arr[i]);
        REQUIRE(tflite::GetTensorData<T>(output_arr[i]));
    }

    arm::app::DetectorPostProcess postp{output_arr[0], output_arr[1], results, nRows, nCols};
    postp.DoPostProcess();

    std::vector<std::vector<arm::app::object_detection::DetectionResult>> expected_results;
    GetExpectedResults(expected_results);

    /* Validate got the same number of boxes */
    REQUIRE(results.size() == expected_results[imageIdx].size());


    for (int i=0; i < (int)results.size(); i++) {
        /* Validate confidence and box dimensions */
        REQUIRE(std::abs(results[i].m_normalisedVal - expected_results[imageIdx][i].m_normalisedVal) < 0.1);
        REQUIRE(static_cast<int>(results[i].m_x0) == Approx(static_cast<int>((T)expected_results[imageIdx][i].m_x0)).epsilon(tolerance));
        REQUIRE(static_cast<int>(results[i].m_y0) == Approx(static_cast<int>((T)expected_results[imageIdx][i].m_y0)).epsilon(tolerance));
        REQUIRE(static_cast<int>(results[i].m_w) == Approx(static_cast<int>((T)expected_results[imageIdx][i].m_w)).epsilon(tolerance));
        REQUIRE(static_cast<int>(results[i].m_h) == Approx(static_cast<int>((T)expected_results[imageIdx][i].m_h)).epsilon(tolerance));
    }
}


TEST_CASE("Running inference with TensorFlow Lite Micro and YoloFastest", "[YoloFastest]")
{
    SECTION("Executing inferences sequentially")
    {
        arm::app::YoloFastestModel model{};

        REQUIRE_FALSE(model.IsInited());
        REQUIRE(model.Init());
        REQUIRE(model.IsInited());

        for (uint32_t i = 0 ; i < NUMBER_OF_FILES; ++i) {
            TestInferenceDetectionResults<uint8_t>(i, model, 1);
        }
    }

    for (uint32_t i = 0 ; i < NUMBER_OF_FILES; ++i) {
        DYNAMIC_SECTION("Executing inference with re-init")
        {
            arm::app::YoloFastestModel model{};

            REQUIRE_FALSE(model.IsInited());
            REQUIRE(model.Init());
            REQUIRE(model.IsInited());

            TestInferenceDetectionResults<uint8_t>(i, model, 1);
        }
    }
}
