/*
 * 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 the CVodHandler class.
 */
/*----------------------------------------------------------*/
#ifndef VODHANDLER_H
#define VODHANDLER_H

#include "Multiplexer.h"
#include "Source.h"
#include "Thread.h"
#include "ConnectionInfo.h"
#include "MostIpc.h"
#include "MacAddr.h"
#include "MsgAddr.h"
#include "MostMsg.h"

typedef enum
{
    SelectFileType_Video = 0,
    SelectFileType_Audio = 1,
    SelectFileType_Radio = 2,
    SelectFileType_Navigation = 3,
    SelectFileType_Cluster = 4
} SelectFileType_t;

/*----------------------------------------------------------*/
/*! \brief Structure holding the file name and the pointer to the CSourceFile object.
 */
/*----------------------------------------------------------*/
typedef struct
{
    char fileName[128];
    CSource *sourceFile;
} BroadcastEntry_t;

/*!
 * \brief  Applications main entry point and event handler, as it implements callbacks from CNetworkListener.
 *         It controls the Network via the CNetwork class.
 *         Isochronous TX connections will be automatically connected to the CMultiplexer class.
 */
class CVodHandler : public CThread
{
private:
    CSafeVector<BroadcastEntry_t *> broadcastFiles;
    CSafeVector<CMultiplexer *> allMultiplexer;
    CSafeVector<char *> ignoreCdevPatterns;
    bool networkManagerFound;
    char networkManagerIP[100];
    bool valuesCleared;
    bool statisticIsEnabled;
    char searchPath[64];
    CConnectionInfoContainer *infoContainer;
    pthread_mutex_t infoContainerMutex;
    
    CMostIpc *mostIpcVod;
    CMsgFilter *vodSelectFile_Set;
    CMsgFilter *vodPlayMode_Set;
    CMsgFilter *vodTimePostion_Set;
    CMsgFilter *vodRepetition_Set;
    CMsgFilter *vodServerVersion_Get;
    CMsgFilter *vodMediaPid_Get;
    CMsgFilter *vodFileList_Get;
    CMsgFilter *vodIndependStream_SetGet;
    CMsgFilter *vodFakeMode_Set;

    CMostIpc *mostIpcNm;
    CMsgFilter *nmServerVersion_Status;
    CMsgFilter *nmConnectionList_Status;

    CVodHandler();
    virtual ~CVodHandler();
    static const char *GetSubPath( SelectFileType_t fileType );
    static bool ExistsFile( const char *pFileName );
    CMultiplexer *GetMultiplexer( const char* deviceName );
    void RegisterBroadcastFiles( SelectFileType_t fileType );
    CMultiplexer *GetMultiplexer( const uint8_t *mac );
    void NM_SendServerVersionGetRequest( const char *ip );

    static void OnVodSelectFile_Set( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodPlayMode_Set( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodTimePosition_Set( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodRepetition_Set( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodServerVersion_Get( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodMediaPid_Get( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodFileList_Get( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnVodIndependentStream_SetGet( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnFakeMode_Set( CMsgAddr *pAddr, CMostMsg *pMsg );

    static void OnNmServerVersion_Status( CMsgAddr *pAddr, CMostMsg *pMsg );
    static void OnNmConnectionList_Status( CMsgAddr *pAddr, CMostMsg *pMsg );
public:

    static CVodHandler *GetInstance();

    static void DestroyInstance();

    void ConnectToNetworkManager();
    void GetConnectionListFromNetworkManager();
    bool CreateMacIndependentStream(uint8_t cdevIndex, uint8_t streamIndex, uint8_t *outMac);
    void CreateSampleStreams( uint8_t amount );

    void SetSearchPath( const char *pSearchPath );
    void SetCdevIgnorePattern( const char *pIgnorePattern );

    /*----------------------------------------------------------*/
    /*! \brief Streams a transport stream file via the specified multiplexer.
     *  \param mac - The MAC address of the sink.
     *  \param fileName - The full path to the transport stream file to play.
     *  \return true, if the stream is acceptable and the multiplexer exists.
     *          false, the stream can not be read or there is no multiplexer assigned with this connection.
     *  \note Make sure, the given sinkIndex points to a TX connection with a valid CMultiplexer object assigned.
     */
    /*----------------------------------------------------------*/
    bool StreamFile( const uint8_t *mac, SelectFileType_t fileType, const char *fileName );

    /*----------------------------------------------------------*/
    /*! \brief Set the pause state for a stream.
     *  \param mac - The MAC address of the sink.
     *  \param isPaused - If set to true, the video file will be paused.
     *  \return true, if the stream pause state could be toggled. false, otherwise.
     *  \note Make sure, the given sinkIndex points to a TX connection with a valid CMultiplexer object assigned.
     *  \note Make sure, that there is a file currently playing. Started with the StreamFile method.
     */
    /*----------------------------------------------------------*/
    bool SetPause( const uint8_t *mac, bool isPaused );

    /*----------------------------------------------------------*/
    /*! \brief Set the repetition state for a stream.
     *  \param mac - The MAC address of the sink.
     *  \param isRepeated - If set to true, the video file will be repeated.
     *  \return true, if the stream repetition state could be toggled. false, otherwise.
     *  \note Make sure, that there is a file currently playing. Started with the StreamFile method.
     */
    /*----------------------------------------------------------*/
    bool SetRepetition( const uint8_t *mac, bool isRepeated );

    /*----------------------------------------------------------*/
    /*! \brief Sets the time position of the given stream.
     *  \param mac - The MAC address of the sink.
     *  \return true, if the stream's time position could be adjusted to given value. false, otherwise.
     *  \note Make sure, that there is a file currently playing. Started with the StreamFile method.
     */
    /*----------------------------------------------------------*/
    bool SetTimePos( const uint8_t *mac, uint16_t timePosPerMile );

    /*----------------------------------------------------------*/
    /*! \brief Stops the playback of the given stream.
     *  \param mac - The MAC address of the sink.
     *  \return true, if the stream was stopped. false, otherwise.
     *  \note Make sure, that there is a file currently playing. Started with the StreamFile method.
     */
    /*----------------------------------------------------------*/
    bool StopStream( const uint8_t *mac );

    /*----------------------------------------------------------*/
    /*! \brief Toggle on / off the printing of Multiplexer Statistics
     */
    /*----------------------------------------------------------*/
    void ToggleStatisticsPrint();

    /*----------------------------------------------------------*/
    /*! \brief Thread method performing the cyclic Multiplexer Statistic prints.
     *  \warning Never call this method directly. Use ToggleStatisticsPrint instead!
     */
    /*----------------------------------------------------------*/
    void Run();
};

#endif //VODHANDLER_H