// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "vpu_test_common_definitions.hpp"
#include "tests_common.hpp"
#include "single_layer_common.hpp"
#include "myriad_layers_reference_functions.hpp"

/* Function to calculate CHW dimensions for the blob generated by */
/* Myriad/HDDL plugin.                                            */
void get_dims(const InferenceEngine::Blob::Ptr blob,
                    int32_t &dimx,
                    int32_t &dimy,
                    int32_t &dimz);

void get_ndims(const InferenceEngine::Blob::Ptr blob,
              int32_t &dimx,
              int32_t &dimy,
              int32_t &dimz,
              int32_t &dimn);

void get_dims(const InferenceEngine::SizeVector& input_dims,
                    int32_t &IW,
                    int32_t &IH,
                    int32_t &IC);

void get_dims(const InferenceEngine::SizeVector& input_dims,
                    int32_t &IW,
                    int32_t &IH,
                    int32_t &IC,
                    int32_t &I_N);

void gen_dims(InferenceEngine::SizeVector& out_dims,
              int32_t dimension,
              int32_t IW,
              int32_t IH,
              int32_t IC);

void gen_dims(InferenceEngine::SizeVector& out_dims,
              int32_t dimension,
              int32_t IW,
              int32_t IH,
              int32_t IC,
              int32_t I_N);

void zeroWeightsRange(uint16_t* ptr,
                      size_t weightsSize);

void defaultWeightsRange(uint16_t* ptr,
                         size_t weightsSize);

void smallWeightsRange(uint16_t* ptr,
                       size_t weightsSize);

std::string gen_param(const param_size& in_param);

#define DEFAULT_SEED_VALUE (43)

#if defined(_MSC_VER)
#  define MAKE_STRUCT(name, ...) [=]()->name{ name make_struct_tmp = {__VA_ARGS__}; return make_struct_tmp; }()
#else
#  define MAKE_STRUCT(name, ...) ((name){__VA_ARGS__})
#endif


struct fcon_test_params {
    tensor_test_params in;
    friend std::ostream& operator<<(std::ostream& os, fcon_test_params const& tst)
    {
        return os << tst.in
                  << ", out_c = " << tst.out_c
                  << ", error_bound = " << tst.error_bound;
    };
    uint32_t out_c;
    float    error_bound;
};

struct interp_test_params {
    size_t iw;
    size_t ih;
    size_t ow;
    size_t oh;
    size_t c;

    friend std::ostream& operator<<(std::ostream& os, interp_test_params const& tst)
    {
        return os << "iw = " << tst.iw << ", "
                  << "ih = " << tst.ih << ", "
                  << "ow = " << tst.ow << ", "
                  << "oh = " << tst.oh << ", "
                  << "channels = " << tst.c;
    };
};

void PrintTo(const IRVersion& version, std::ostream* os);

void PrintTo(const tensor_test_params& sz, std::ostream* os);

void print_buffer_HWC_fp16(InferenceEngine::ie_fp16 *src_data, int32_t IW, int32_t IH, int32_t IC, const char * tname,
        int32_t iw0=0, int32_t iw1=-1, int32_t ih0=0, int32_t ih1=-1, int32_t ic0=0, int32_t ic1=-1);
void print_tensor_HWC_fp16(const InferenceEngine::Blob::Ptr src, const char * tname,
        int32_t iw0=0, int32_t iw1=-1, int32_t ih0=0, int32_t ih1=-1, int32_t ic0=0, int32_t ic1=-1);

PRETTY_PARAM(Dims, tensor_test_params);
PRETTY_PARAM(DimsInput, tensor_test_params);
PRETTY_PARAM(DimsInput3D, tensor_test_params_3d);
PRETTY_PARAM(DimsOutput, tensor_test_params);
PRETTY_PARAM(DimsOutput3D, tensor_test_params_3d);

/*this helper class is defined to add post op operation without significant */
/* modification of the existing codebase                                    */

void GenRandomData(InferenceEngine::Blob::Ptr blob);
bool fromBinaryFile(std::string input_binary, InferenceEngine::Blob::Ptr blob);

WeightsBlob* GenWeights(size_t sz,
                                            float min_val = -1.0f,
                                            float max_val = 1.0f);
