/*
 * Copyright (c) 2021 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 "RNNoiseModel.hpp"
#include "TensorFlowLiteMicro.hpp"
#include "TestData_noise_reduction.hpp"

#include <catch.hpp>
#include <random>

bool RunInference(arm::app::Model& model, std::vector<int8_t> vec,
                    const size_t sizeRequired, const size_t dataInputIndex)
{
    TfLiteTensor* inputTensor = model.GetInputTensor(dataInputIndex);
    REQUIRE(inputTensor);
    size_t copySz = inputTensor->bytes < sizeRequired ? inputTensor->bytes : sizeRequired;
    const int8_t* vecData = vec.data();
    memcpy(inputTensor->data.data, vecData, copySz);
    return model.RunInference();
}

void genRandom(size_t bytes, std::vector<int8_t>& randomAudio)
{
    randomAudio.resize(bytes);
    std::random_device rndDevice;
    std::mt19937 mersenneGen{rndDevice()};
    std::uniform_int_distribution<short> dist {-128, 127};
    auto gen = [&dist, &mersenneGen](){
        return dist(mersenneGen);
    };
    std::generate(std::begin(randomAudio), std::end(randomAudio), gen);
}

bool RunInferenceRandom(arm::app::Model& model, const size_t dataInputIndex)
{
    std::array<size_t, 4> inputSizes = {IFM_0_DATA_SIZE, IFM_1_DATA_SIZE, IFM_2_DATA_SIZE, IFM_3_DATA_SIZE};
    std::vector<int8_t> randomAudio;
    TfLiteTensor* inputTensor = model.GetInputTensor(dataInputIndex);
    REQUIRE(inputTensor);
    genRandom(inputTensor->bytes, randomAudio);

    REQUIRE(RunInference(model, randomAudio, inputSizes[dataInputIndex], dataInputIndex));
    return true;
}

TEST_CASE("Running random inference with TensorFlow Lite Micro and RNNoiseModel Int8", "[RNNoise]")
{
    arm::app::RNNoiseModel model{};

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

    model.ResetGruState();

    for (int i = 1; i < 4; i++ ) {
        TfLiteTensor* inputGruStateTensor = model.GetInputTensor(i);
        auto* inputGruState = tflite::GetTensorData<int8_t>(inputGruStateTensor);
        for (size_t tIndex = 0;  tIndex < inputGruStateTensor->bytes; tIndex++) {
            REQUIRE(inputGruState[tIndex] == arm::app::GetTensorQuantParams(inputGruStateTensor).offset);
        }
    }

    REQUIRE(RunInferenceRandom(model, 0));
}

class TestRNNoiseModel : public arm::app::RNNoiseModel
{
public:
    bool CopyGruStatesTest() {
        return RNNoiseModel::CopyGruStates();
    }

    std::vector<std::pair<size_t, size_t>> GetStateMap() {
        return  m_gruStateMap;
    }

};

template <class T>
void printArray(size_t dataSz, T data){
    char strhex[8];
    std::string strdump;

    for (size_t i = 0; i < dataSz; ++i) {
        if (0 == i % 8) {
            printf("%s\n\t", strdump.c_str());
            strdump.clear();
        }
        snprintf(strhex, sizeof(strhex) - 1,
                 "0x%02x, ", data[i]);
        strdump += std::string(strhex);
    }

    if (!strdump.empty()) {
        printf("%s\n", strdump.c_str());
    }
}

/* This is true for gcc x86 platform, not guaranteed for other compilers and platforms. */
TEST_CASE("Test initial GRU out state is 0", "[RNNoise]")
{
    TestRNNoiseModel model{};
    model.Init();

    auto map = model.GetStateMap();

    for(auto& mapping: map) {
        TfLiteTensor* gruOut = model.GetOutputTensor(mapping.first);
        auto* outGruState = tflite::GetTensorData<uint8_t>(gruOut);

        printf("gru out state:");
        printArray(gruOut->bytes, outGruState);

        for (size_t tIndex = 0;  tIndex < gruOut->bytes; tIndex++) {
            REQUIRE(outGruState[tIndex] == 0);
        }
    }

}

TEST_CASE("Test GRU state copy", "[RNNoise]")
{
    TestRNNoiseModel model{};
    model.Init();
    REQUIRE(RunInferenceRandom(model, 0));

    auto map = model.GetStateMap();

    std::vector<std::vector<uint8_t>> oldStates;
    for(auto& mapping: map) {

        TfLiteTensor* gruOut = model.GetOutputTensor(mapping.first);
        auto* outGruState = tflite::GetTensorData<uint8_t>(gruOut);
        /* Save old output state. */
        std::vector<uint8_t> oldState(gruOut->bytes);
        memcpy(oldState.data(), outGruState, gruOut->bytes);
        oldStates.push_back(oldState);
    }

    model.CopyGruStatesTest();
    auto statesIter = oldStates.begin();
    for(auto& mapping: map) {
        TfLiteTensor* gruInput = model.GetInputTensor(mapping.second);
        auto* inGruState = tflite::GetTensorData<uint8_t>(gruInput);
        for (size_t tIndex = 0;  tIndex < gruInput->bytes; tIndex++) {
            REQUIRE((*statesIter)[tIndex] == inGruState[tIndex]);
        }
        statesIter++;
    }

}