#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/prctl.h>
#include "com_IPMI_App.h"
#include "com_IPMIDefs.h"
#include "com_Message.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

/**
 ** @fn PostMsg
 ** @brief Post a message to the destination task.
 ** @param MsgPkt   - Message to be posted.
 ** @param Queue       - Queue to post this message to.
 ** @return   0 if success, -1 if failed.
 ***/
int
PostMsg (int fd, MsgPkt_T* pMsgPkt)
{
    int     Err,i=0;
    uint16_t  Size;

    Size    = sizeof (MsgPkt_T) - MSG_PAYLOAD_SIZE + pMsgPkt->Size;
    
    Err = write (fd, pMsgPkt, Size) ;
    if ((Err == -1) || (Err != Size))
    {
        printf ("Message.c : PostMsg %x %s\n",errno, strerror(errno));
        return -1;
    }             

    //printf("---> PostMsg ok, fd = %d\n", fd);
    return 0;
}


/*------ Get the message from the queue -----------------------------*/
int OS_GET_FROM_Q( int fd, uint8_t *pBuf, int Size, int16_t timeout)    
{                                                           
    int ReadLen = 0, Left, Len;
    int Err = 0;                             
    Left = Size;                                            
    while( Left > 0 )                                       
    {                                                       
        Len = read (fd, (uint8_t*)pBuf + ReadLen, Left ); 
        if( Len < 0 )                                       
        {                                                   
            if( errno == EINTR || errno == EAGAIN )         
            {                                               
                continue;                                   
            }                                               
            else                                            
            {                                               
                Err = -1;                                 
                break;                                      
            }                                               
        }                                                   
        ReadLen += Len;                                     
        Left -= Len;                                        
    }                                                       
    Err = ReadLen;                                        
    return Err;
}

/**
 * @fn GetMsg
 * @brief Gets the message posted to this task.
 * @param MsgPkt   - Pointer to the buffer to hold the message packet.
 * @param Queue    - Queue to fetch the message from.
 * @param Timeout    - Number of seconds to wait.
 * 
 * WAIT_NONE       - If the function has to return immediately.
 * WAIT_INFINITE   - If the function has to wait infinitely.
 * NOTE :
 * @return   0 if success, -1 if failed.
**/
int
GetMsg (int fd, MsgPkt_T* pMsgPkt, int16_t Timeout)
{
    int     Err;
    int     Size;
    
    /* check for limited wait time */
    if (Timeout >= 0)
    {
        struct timeval      Timeval;
        fd_set              fdRead;
        int                 n, RetVal;

        FD_ZERO (&fdRead);
        FD_SET (fd, &fdRead);
        n = fd + 1;

        Timeval.tv_sec  = Timeout;
        Timeval.tv_usec = 0;
        RetVal = select (n, &fdRead, NULL, NULL, &Timeval);
        if (-1 == RetVal)
        {
            printf ("Message.c : Error waiting on Queue, log1\n");
            return -1;
        }
        else if (0 == RetVal)
        {
            //printf ("Message.c : Error waiting on Queue, log2\n");
            return -2;
        }
    }

    /* Get the header first*/
    Size = sizeof (MsgPkt_T) - MSG_PAYLOAD_SIZE;

    if(-1 == OS_GET_FROM_Q (fd, (uint8_t*)pMsgPkt, Size, WAIT_INFINITE))
    {
        printf ("Message.c : GetMsg %s\n",strerror(errno));
        return -1;
    }

    /* Get the payload data */
    Size = pMsgPkt->Size;
    if(-1 == OS_GET_FROM_Q (fd, pMsgPkt->Data, Size, WAIT_INFINITE))
    {
        printf ("Message.c : GetMsg %s\n",strerror(errno));
        return -1;
    }

    return 0;
}