////////////////////////////////////////////////////////////////////////////////
//                                                                             /
// 2012-2019 (c) Baical                                                        /
//                                                                             /
// This library is free software; you can redistribute it and/or               /
// modify it under the terms of the GNU Lesser General Public                  /
// License as published by the Free Software Foundation; either                /
// version 3.0 of the License, or (at your option) any later version.          /
//                                                                             /
// This library is distributed in the hope that it will be useful,             /
// but WITHOUT ANY WARRANTY; without even the implied warranty of              /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU           /
// Lesser General Public License for more details.                             /
//                                                                             /
// You should have received a copy of the GNU Lesser General Public            /
// License along with this library.                                            /
//                                                                             /
////////////////////////////////////////////////////////////////////////////////
#ifndef BK_API_TELEMETRY_STORAGE_H
#define BK_API_TELEMETRY_STORAGE_H

#include "PAPI.h"

/// <summary> GUID of the reader </summary>
#define BK_READER_GUID_TELEMETRY { 0xD6C2CCE3, 0xCA34, 0x4B0A, { 0x35, 0xC8, 0xAB, 0x85, 0x27, 0x7F, 0xB7, 0xDA } }

namespace Bk
{
    PRAGMA_PACK_ENTER(2)
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> General information about telemetry stream </summary>
    struct stTelemetryInfo
    {
        /// <summary> amount of registered counters </summary>
        tUINT16 wCounters;  
        /// <summary> duration in 100ns intervals </summary>
        tUINT64 qwDuration; 
        /// <summary> samples count for all registered counters </summary>
        tUINT64 qwSamples;  
    }ATTR_PACK(2);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Structure describes one telemetry sample (value) </summary>
    struct stTelemetrySample
    {
        /// <summary> time offset in 100ns intervals, value between 0 and Bk::stTelemetryInfo::qwDuration </summary>
        tUINT64 qwTime;     
        /// <summary> sample value </summary>
        tDOUBLE dbValue; 
        /// <summary> counter ID </summary>
        tUINT16 wID; 
    }ATTR_PACK(2);

#if defined(UTF8_ENCODING)
    #define TEL_COUNTER_NAME_LEN (P7TELEMETRY_COUNTER_NAME_LENGTH * 2)
#else
    #define TEL_COUNTER_NAME_LEN P7TELEMETRY_COUNTER_NAME_LENGTH
#endif

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> describes telemetry counter </summary>
    struct stTelemetryCounter
    {
        /// <summary> On/Off flag, dynamic parameter </summary>
        tBOOL bOn;
        /// <summary> calculated minimal counter's value, dynamic parameter </summary>
        tDOUBLE dbMin_Real;
        /// <summary> calculated maximal counter's value, dynamic parameter </summary>
        tDOUBLE dbMax_Real;
        /// <summary> calculated average counter's value, dynamic parameter </summary>
        tDOUBLE dbAvg_Real;
        /// <summary> samples count, dynamic parameter </summary>
        tUINT64 qwSamples;
        /// <summary> initialized flag (1/0), static parameters </summary>
        tBOOL bInitialized;
        /// <summary> Minimal counter value specified by used on creation, static parameters </summary>
        tDOUBLE dbMin;
        /// <summary> Alarm min counter value specified by used on creation, static parameters </summary>
        tDOUBLE dbAlarmMin;
        /// <summary> Maximal counter value specified by used on creation, static parameters </summary>
        tDOUBLE dbMax;
        /// <summary> Alarm max counter value specified by used on creation, static parameters </summary>
        tDOUBLE dbAlarmMax;
        /// <summary> counter's name, static parameters </summary>
        const tXCHAR *pName;

        // stTelemetryCounter()
        // {
        //     bOn          = FALSE;
        //     dbMin_Real   = 0.0;
        //     dbMax_Real   = 0.0;
        //     dbAvg_Real   = 0.0;
        //     qwSamples    = 0ll;
        //     bInitialized = FALSE;
        //     dbMin        = 0.0;
        //     dbAlarmMin   = 0.0;
        //     dbMax        = 0.0;
        //     dbAlarmMax   = 0.0;
        //     pName        = NULL;
        // }
    }ATTR_PACK(2);
    PRAGMA_PACK_EXIT()


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Counter value detalisation </summary>
    enum eTelemetryCounterValue
    {
        /// <summary> Only static values </summary>
        eTelemetryStaticValue   = 1,
        /// <summary> Only dynamic values </summary>
        eTelemetryDynamicValue     ,
        /// <summary> dynamic + static values </summary>
        eTelemetryAllValues          
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Telemetry reader interface </summary>
    class ITelemetryReader
    {
    public:
        /// <summary> Gets general telemetry channel info </summary>
        /// <param name="o_pInfo"> telemetry info structure, output parameter</param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Info(Bk::stTelemetryInfo *o_pInfo) = 0;

        /// <summary> Gets ID of new registered counter </summary>
        /// <param name="o_rId"> telemetry counter ID</param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Pull_New_Counter(tUINT16 &o_rId) = 0;

        /// <summary> Gets count of new registered counters </summary>
        /// <returns>count</returns>  
        virtual tUINT32 __stdcall Get_New_Counters_Count() = 0;

        /// <summary> Gets counter info </summary>
        /// <param name="i_bIndex"> counter index [0 .. (stTelemetryInfo::wCounters-1)]</param>
        /// <param name="o_pCounter"> counter info </param>
        /// <param name="i_eDetails"> detalisation level </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Counter(tUINT16                    i_wIndex, 
                                                  Bk::stTelemetryCounter    *o_pCounter, 
                                                  Bk::eTelemetryCounterValue i_eDetails) = 0;

        /// <summary> Gets nearest sample index using time offset </summary>
        /// <param name="i_qwTime"> time in 100ns intevals, from 0 to Bk::stTelemetryInfo::qwDuration</param>
        /// <param name="o_pIndex"> index value, MAXUINT64 is not valid value, mean that index isn't found, output value </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Nearest_Index(tUINT64 i_qwTime, tUINT64 *o_pIndex) = 0;

        /// <summary> Gets samples </summary>
        /// <param name="i_qwIndex"> 
        ///  index, [0 .. (stTelemetryInfo::qwSamples-1)]
        ///  Time can be converted to index using Get_Nearest_Index function 
        /// </param>
        /// <param name="o_pSamples"> buffer to store sampels </param>
        /// <param name="i_dwCount"> maximal amount of samples for reading, o_pSamples buffer has to be large enough </param>
        /// <param name="o_dwCount"> real amount of samples returned by function, output parameter </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Samples(tUINT64                i_qwIndex, 
                                                  Bk::stTelemetrySample *o_pSamples, 
                                                  tUINT32                i_dwCount, 
                                                  tUINT32               *o_dwCount) = 0;

        /// <summary> Increases object reference counter </summary>
        /// <returns> new value of reference counter </returns>  
        virtual tINT32 __stdcall Add_Ref() = 0;

        /// <summary> Decreases object reference counter. If 0 - object will be self-destroyed </summary>
        /// <returns> new value of reference counter </returns>  
        virtual tINT32 __stdcall Release() = 0;
    };                                                                    
}

#endif //BK_API_TELEMETRY_STORAGE_H