/*
 * Video On Demand Samples
 *
 * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * You may also obtain this software under a propriety license from Microchip.
 * Please contact Microchip for further information.
 *
 */

/*----------------------------------------------------------*/
/*! \file
 *  \brief This file contains a helper class to store MOST connections
 */
/*----------------------------------------------------------*/
#ifndef CONNECTIONINFO_H
#define CONNECTIONINFO_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "SafeVector.h"
#include "Types.h"
#include "MacAddr.h"

/*!
 * \brief  This is a helper class for the CNetworkManagerHandler. It keeps track of the reported connections
 * and the instanced CMultiplexer classes.
 */
class CConnectionInfo
{
public:
    CConnectionInfo();
    CConnectionInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance, bool isTx );
    ~CConnectionInfo();

    ///The Ethernet MAC address of this connection.
    CMacAddr *macAddr;

    ///The device type as specified in XML file and configured in the config string (Group-Address)
    TDeviceId deviceType;

    ///The instance count of this device class. Starting at 0 for the first instance. Incremented with every occurrence.
    uint8_t deviceInstance;

    ///The channel ID as declared in the configuration XML file.
    TChannelId channelId;

    ///The MOST ring instance. Starting at 0 for the first MOST ring, on the first OS81110.
    TMostInstace mostInstance;

    ///The MOST data used by this channel.
    EPDataType_t dataType;

    ///The reserved MOST bandwidth in bytes for this channel.
    TBlockwidth reservedBandwidth;

    ///The amount of bytes reserved for this channel in Driver. If no buffers were allocated, this value is -1.
    int32_t bufferSize;

    ///In case this is a local connection, the path of the character device is stored in this variable. (e.g. /dev/mdev0).
    char deviceName[64];

    ///TRUE if this connections is a source. FALSE if this connection is a sink,
    bool isTX;

    //TRUE, if the input socket of this connection was successfully created.
    bool inSocketCreated;

    //TRUE, if the output socket of this connection was successfully created.
    bool outSocketCreated;

    //TRUE, if the input socket and the output socket of this connection were successfully connected.
    bool socketsConnected;

    ///The MOST connection label.
    uint32_t mostConnectionLabel;

    ///If this socket is a splitted / combined socket, this value holds the offset in byte. -1 if this is a normal socket.
    int16_t splittedOffset;

    ///If this socket is a splitted / combined socket, this value holds the maximum bandwidth of all splitted sockets in byte. -1 if this is a normal socket.
    int16_t splittedMaxBandwidth;
    
    ///This is USB specific. It describes how many sub-frames are concatenated into a single USB microframe.
    uint16_t packetsPerXact;
};

/*!
 * \brief  This is a storage class holding multiple CConnectionInfo in a container.
 *         It supports adding, removing, serializing and deserializing
 */
class CConnectionInfoContainer
{
private:
    CSafeVector<CConnectionInfo *> allInfos;
    bool Compare( CConnectionInfo *c, CConnectionInfo *t );
public:

    /*----------------------------------------------------------*/
    /*! \brief Default Constructor of CConnectionInfoContainer
     */
    /*----------------------------------------------------------*/
    CConnectionInfoContainer();

    /*----------------------------------------------------------*/
    /*! \brief Default Destructor of CConnectionInfoContainer
     */
    /*----------------------------------------------------------*/
    ~CConnectionInfoContainer();



    /*----------------------------------------------------------*/
    /*! \brief Gets the amount of entries stored in the whole database.
     *  \return The amount of entries.
     */
    /*----------------------------------------------------------*/
    uint32_t GetAllInfoAmount();



    /*----------------------------------------------------------*/
    /*! \brief Gets the information at the corresponding position.
     *  \param index - the position inside the database
     *  \note Use GetAllInfoAmount() to get the max index (n-1).
     *  \return The information if found, NULL if out of range
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetInfo( uint32_t index );


    /*----------------------------------------------------------*/
    /*! \brief Compares to container.
     *  \param containerToCompare - The container to compare.
     *  \return true, if both containers stores the same information. false, otherwise.
     */
    /*----------------------------------------------------------*/
    bool Compare( CConnectionInfoContainer *containerToCompare );



    /*----------------------------------------------------------*/
    /*! \brief Checks if the given information is already stored inside the database.
     *  \param checkInfo - the information object to be checked
     *  \return true, if the information is already stored inside the database. false, otherwise.
     */
    /*----------------------------------------------------------*/
    bool ExistsEntry( CConnectionInfo *checkInfo );


    /*----------------------------------------------------------*/
    /*! \brief Gets an info object with the given parameters
     *  \param macAddr - The MAC address of the device
     *  \param channelId - The channel identifier as used in the XML file.
     *  \param mostInstance - The MOST ring instance, starting 0 for the first MOST instance.
     *  \return The info object if found. NULL, otherwise.
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance );


    /*----------------------------------------------------------*/
    /*! \brief Gets the amount of devices with the same 
     *  \param mostInstance - The MOST ring instance. Starting at 0 for the first MOST ring.
     *  \param deviceId - The device ID as declared in the configuration XML file.
     *  \return The Amount of devices found, with the given deviceId
     */
    /*----------------------------------------------------------*/
    uint8_t GetAmountOfDevices( TMostInstace mostInstance, TDeviceId deviceId );


    /*----------------------------------------------------------*/
    /*! \brief Helper function, which delivers a CConnectionInfo object to the given search parameters.
     *  \param macAddr - Searches for the given MAC address.
     *  \param channelId - Search for the given Channel address.
     *  \param mostInstance - Search on the given MOST ring instance.
     *  \param isTx - true, search for a transmission connection. false, search for a reception connection.
     *  \return An pointer to the matching CConnectionInfo object if found. NULL otherwise.
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance, bool isTx );


    /*----------------------------------------------------------*/
    /*! \brief Stores the given information inside the database.
     *  \param info - The information to be stored.
     */
    /*----------------------------------------------------------*/
    void AddInfo( CConnectionInfo *info );


    /*----------------------------------------------------------*/
    /*! \brief Helper function, which deletes all stored informations retrieved so far.
     */
    /*----------------------------------------------------------*/
    void DestroyAllInfos();


    /*----------------------------------------------------------*/
    /*! \brief Helper function, which delete the information matching to the given parameters.
     *  \param macAddr - Searches for the given MAC address.
     *  \param channelId - Search for the given Channel address.
     *  \param mostInstance - Search on the given MOST ring instance.
     */
    /*----------------------------------------------------------*/
    void DestroyInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance );

    /*----------------------------------------------------------*/
    /*! \brief Helper function, which prints all available information to the console.
     *  \param hideTx - true, when transmission connections shall not be shown in the table.
     *  \param hideRx - true, when reception connections shall not be shown in the table.
     */
    /*----------------------------------------------------------*/
    void PrintTable( bool hideTx, bool hideRx );

    /*----------------------------------------------------------*/
    /*! \brief Serializes all connection informations to multi line string.
     *  \param pBuffer, buffer which then will hold the serialized string.
     *  \param bufferLen, the size of the given buffer.
     * \return The amount of bytes used from the given buffer.
     */
    /*----------------------------------------------------------*/
    uint32_t SerializeToString( char *pBuffer, uint32_t bufferLen );

    /*----------------------------------------------------------*/
    /*! \brief Deserializes all connection informations to multi line string.
     *  \param pBuffer, buffer which will read of the serialized string.
     * \return True, if the string could be used to deserialize all data. False, error occurred.
     * \note The given buffer will be manipulated by strtok operation!
     */
    /*----------------------------------------------------------*/
    bool DeserializeFromString( char *pBuffer );


    /*----------------------------------------------------------*/
    /*! \brief Returns the amount of entries, which contains a CDEV device name
     *  \return The amount of devices.
     */
    /*----------------------------------------------------------*/
    uint32_t GetAmountOfCDevs();


    /*----------------------------------------------------------*/
    /*! \brief Retrieves the information of the specific CDEV.
     *  \param cdevInst - The index of the CDEV device, starting with 0 for the first device.
     *  \note Use GetAmountOfCDevs() the get the maximum possible index (n-1).
     *  \return The information object, if found. NULL, otherwise.
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetConnectionInfoOfCdev( uint32_t cdevInst );



    /*----------------------------------------------------------*/
    /*! \brief Retrieves the information of the specific CDEV.
     *  \param cdevInst - The index of the CDEV device, starting with 0 for the first device.
     *  \param splittedIndex - Index of splitted socket entry, starting with 0 for the first splitted entry which has an offset greater than zero.
     *  \note Use GetAmountOfCDevs() the get the maximum possible index (n-1).
     *  \return The information object, if found. NULL, otherwise.
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetConnectionInfoOfCdev( uint32_t cdevInst, uint32_t splittedIndex );


    /*----------------------------------------------------------*/
    /*! \brief Returns the amount of entries, which acts as a sink channel.
     *  \return The amount of devices.
     */
    /*----------------------------------------------------------*/
    uint32_t GetAmountOfSinks();


    /*----------------------------------------------------------*/
    /*! \brief Retrieves the information of the specific sink.
     *  \param cdevInst - The index of the sink, starting with 0 for the sink.
     *  \note Use GetAmountOfSinks() the get the maximum possible index (n-1).
     *  \return The information object, if found. NULL, otherwise.
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetConnectionInfoOfSink( uint32_t sinkInst );



    /*----------------------------------------------------------*/
    /*! \brief Gets the information object by the given MAC address.
     *  \param mac - The MAC address of the searched device.
     *  \return The information object, if found. NULL, otherwise. 
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetConnectionInfoByMacAddress( const uint8_t *mac );


    /*----------------------------------------------------------*/
    /*! \brief Gets the opposite device information connected with given MAC address.
     *  \param mac - The MAC address of the device, which then the information of connected opposite device is returned.
     *  \return The information object, if found. NULL, otherwise.
     */
    /*----------------------------------------------------------*/
    CConnectionInfo *GetRemoteConnectionInfoByMacAddress( const uint8_t *mac );
};

#endif //CONNECTIONINFO_H