#include "iqi_fast_processing_example.h"
#include "iqi_mst.h"
#include "iqi_fast_processing.h"

//#define FAST_PROCESSING_EXAMPLE_PERFORMANCE_TEST

static int16 ReadApplicationTag(uint16 uiPortNo, unsigned int mode, unsigned int* response_length, char08* cpErrMsg);
static int16 WriteApplicationTag(uint16 uiPortNo, uchar08 length, unsigned int mode, char08* cpErrMsg);

int16 fast_processing_example_StartTest(
    uint16 uiPortNo,
    char08* cpErrMsg)
{
    int16 error_resut = ERR_CUSTOM;
    //Interference mode is applied only for PREOPERATE and OPERATE mode

    do
    {
        uchar08 recv_buffer[256];
        // try to set operating mode to Inactive (Fallback)
        int16 error_resut_help = mst_SetOperatingMode(uiPortNo, MST_OPERATING_MODE_INACTIVE,
            MST_STATE_INACTIVE, recv_buffer, cpErrMsg);
        if (error_resut_help != ERR_NONE)
        {
            error_resut = error_resut_help;
            break;
        }
        mst_StateT state = (mst_StateT)recv_buffer[0];
        printf("go to inactive: state %d\n", state);

        // try to set operating mode to Auto (permanent seach of IO-Link device)
        error_resut_help = mst_SetOperatingMode(uiPortNo, MST_OPERATING_MODE_AUTO,
            MST_STATE_OPERATE, recv_buffer, cpErrMsg);
        if (error_resut_help < ERR_NONE)
        {
            error_resut = error_resut_help;
            break;
        }
        state = (mst_StateT)recv_buffer[0];
        printf("go to operate: state %d\n", state);

#ifndef FAST_PROCESSING_EXAMPLE_PERFORMANCE_TEST
        //activate 
        error_resut_help = fast_processing_Activate(uiPortNo, cpErrMsg);
        if (error_resut_help < ERR_NONE)
        {
            error_resut = error_resut_help;
            break;
        }
#endif

#ifdef FAST_PROCESSING_EXAMPLE_PERFORMANCE_TEST
        unsigned int tests_quantity = 100;

        clock_t start, end;
        double total_t;
        error_resut_help = ERR_NONE;

        for (unsigned int mode = 0; mode <= 1; mode++)
        {
            if (mode == 1)
            {
                //activate 
                error_resut_help = fast_processing_Activate(uiPortNo, cpErrMsg);
                if (error_resut_help < ERR_NONE)
                {
                    error_resut = error_resut_help;
                    break;
                }
            }
            start = clock();

            for (unsigned int counter = 0; counter < tests_quantity; counter++)
            {
#else
                unsigned int mode = 1; //fast processing
#endif
                unsigned int response_length = 32;
                error_resut_help = ReadApplicationTag(uiPortNo, mode, &response_length, cpErrMsg);
                if (error_resut_help < ERR_NONE)
                {
                    error_resut = error_resut_help;
                    break;
                }

                error_resut_help = WriteApplicationTag(uiPortNo, (uchar08)response_length, mode, cpErrMsg);
                if (error_resut_help < ERR_NONE)
                {
                    error_resut = error_resut_help;
                    break;
                }
#ifdef FAST_PROCESSING_EXAMPLE_PERFORMANCE_TEST
            }
            if (error_resut_help < ERR_NONE)
            {
                break;
            }
            end = clock();
            total_t = (double)(end - start) / CLOCKS_PER_SEC;
            printf("Duration for mode: %u, : %f\n", mode, total_t);
        }
#endif
        if (error_resut_help < ERR_NONE)
        {
            break;
        }

        error_resut = ERR_NONE;
    } while (0);

    //deactivate 
    fast_processing_Deactivate(uiPortNo, cpErrMsg);

    if (error_resut < ERR_NONE)
    {
        printf("FAILED: %s\n", cpErrMsg);
    }

    return error_resut;
}

int16 ReadApplicationTag(uint16 uiPortNo, unsigned int mode, unsigned int* response_length, char08* cpErrMsg)
{
    int16 error_result = ERR_CUSTOM;
    printf("read application tag... : ");
    uchar08 od_buffer[MAX_OD_BUF_LEN] = { 0 };
    uint16 uiISDUErr = 0;
    int16 odSize;
    if (mode == 0)
    {
        odSize = mst_ReadOD(uiPortNo, 24, 0x00, od_buffer, 255, &uiISDUErr, cpErrMsg);
    }
    else
    {
        odSize = fast_processing_ReadOD(uiPortNo, 24, 0x00, od_buffer, 255, &uiISDUErr, cpErrMsg);
    }

    if (odSize < 0)
    {
        //error
        error_result = ERR_OPERATION;
    }
    else if (odSize == 0)
    {
        snprintf(cpErrMsg, MAX_ERR_STR_LEN, MAX_ERR_STR_LEN, "On-request read data response size is zero.");
        error_result = ERR_INTERNAL;
    }
    else
    {
        printf("%s\n", od_buffer);
        error_result = ERR_NONE;
        *response_length = odSize;
    }
    return error_result;
}

int16 WriteApplicationTag(uint16 uiPortNo, uchar08 length, unsigned int mode, char08* cpErrMsg)
{
    int16 error_result = ERR_CUSTOM;
    uchar08 od_buffer[MAX_OD_BUF_LEN] = { 0 };
    for (unsigned int index = 0; index < length; index++)
    {
        od_buffer[index] = 0x41 + index; //start from capital A
        if (od_buffer[index] > 90) //skip special symbols
        {
            od_buffer[index] += 6;
        }
    }
    printf("write application tag: %s, ...\n", od_buffer);
    uint16 uiISDUErr = 0;
    if (mode == 0)
    {
        error_result = mst_WriteOD(uiPortNo, 24, 0x00, od_buffer, length, &uiISDUErr, cpErrMsg);
    }
    else
    {
        error_result = fast_processing_WriteOD(uiPortNo, 24, 0x00, od_buffer, length, &uiISDUErr, cpErrMsg);
    }

    return error_result;
}