/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtcp_receiver_help.h"
#include "rtp_utility.h"

#include <string.h> //memset
#include <cassert> //assert

namespace webrtc {
using namespace RTCPHelp;

RTCPPacketInformation::RTCPPacketInformation() :
    rtcpPacketTypeFlags(0),
    nackSequenceNumbers(0),
    nackSequenceNumbersLength(0),
    applicationSubType(0),
    applicationName(0),
    applicationData(),
    applicationLength(0),
    reportBlock(false),
    fractionLost(0),
    roundTripTime(0),
    lastReceivedExtendedHighSeqNum(0),
    jitter(0),
    sliPictureId(0),
    rpsiPictureId(0),
    VoIPMetric(NULL)
{
}

RTCPPacketInformation::~RTCPPacketInformation()
{
    delete [] nackSequenceNumbers;
    delete [] applicationData;
    delete VoIPMetric;
}

void
RTCPPacketInformation::AddVoIPMetric(const RTCPVoIPMetric* metric)
{
    VoIPMetric = new RTCPVoIPMetric();
    memcpy(VoIPMetric, metric, sizeof(RTCPVoIPMetric));
}

void
RTCPPacketInformation::AddApplicationData(const WebRtc_UWord8* data, const WebRtc_UWord16 size)
{
    WebRtc_UWord8* oldData = applicationData;
    WebRtc_UWord16 oldLength = applicationLength;

    applicationLength += size;
    applicationData = new WebRtc_UWord8[applicationLength];

    if(oldData)
    {
        memcpy(applicationData, oldData, oldLength);
        memcpy(applicationData+oldLength, data, size);
        delete [] oldData;
    } else
    {
        memcpy(applicationData, data, size);
    }
}

void
RTCPPacketInformation::ResetNACKPacketIdArray()
{
    if(NULL == nackSequenceNumbers)
    {
        nackSequenceNumbers = new WebRtc_UWord16[NACK_PACKETS_MAX_SIZE];
    }
    nackSequenceNumbersLength = 0;
}

void
RTCPPacketInformation::AddNACKPacket(const WebRtc_UWord16 packetID)
{
    assert(nackSequenceNumbers);

    WebRtc_UWord16& idx = nackSequenceNumbersLength;
    if (idx < NACK_PACKETS_MAX_SIZE)
    {
        nackSequenceNumbers[idx++] = packetID;
    }
}

void
RTCPPacketInformation::AddReportInfo(const WebRtc_UWord8 fraction,
                                     const WebRtc_UWord16 rtt,
                                     const WebRtc_UWord32 extendedHighSeqNum,
                                     const WebRtc_UWord32 j)
{
    reportBlock = true;
    fractionLost = fraction;
    roundTripTime = rtt;
    jitter = j;
    lastReceivedExtendedHighSeqNum = extendedHighSeqNum;
}

RTCPReportBlockInformation::RTCPReportBlockInformation():
    remoteReceiveBlock(),
    remoteMaxJitter(0),
    RTT(0),
    minRTT(0),
    maxRTT(0),
    avgRTT(0),
    numAverageCalcs(0)
{
    memset(&remoteReceiveBlock,0,sizeof(remoteReceiveBlock));
}

RTCPReportBlockInformation::~RTCPReportBlockInformation()
{
}

RTCPReceiveInformation::RTCPReceiveInformation() :

    lastTimeReceived(0),
    lastFIRSequenceNumber(-1),
    lastFIRRequest(0),
    readyForDelete(false),
    _tmmbrSetTimeouts(NULL)
{
}

RTCPReceiveInformation::~RTCPReceiveInformation()
{
    if(_tmmbrSetTimeouts)
    {
        delete [] _tmmbrSetTimeouts;
    }
}

// don't use TmmbrSet.VerifyAndAllocate this version keeps the data
void
RTCPReceiveInformation::VerifyAndAllocateTMMBRSet(const WebRtc_UWord32 minimumSize)
{
    if(minimumSize > TmmbrSet.sizeOfSet)
    {
        // make sure that our buffers are big enough
        WebRtc_UWord32* ptrTmmbrSet = new WebRtc_UWord32[minimumSize];
        WebRtc_UWord32* ptrTmmbrPacketOHSet = new WebRtc_UWord32[minimumSize];
        WebRtc_UWord32* ptrTmmbrSsrcSet = new WebRtc_UWord32[minimumSize];
        WebRtc_UWord32* tmmbrSetTimeouts = new WebRtc_UWord32[minimumSize];

        if(TmmbrSet.lengthOfSet > 0)
        {
            // copy old values
            memcpy(ptrTmmbrSet, TmmbrSet.ptrTmmbrSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
            memcpy(ptrTmmbrPacketOHSet, TmmbrSet.ptrPacketOHSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
            memcpy(ptrTmmbrSsrcSet, TmmbrSet.ptrSsrcSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
            memcpy(tmmbrSetTimeouts, _tmmbrSetTimeouts, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
        }
        if(TmmbrSet.ptrTmmbrSet)
        {
            delete [] TmmbrSet.ptrTmmbrSet;
            delete [] TmmbrSet.ptrPacketOHSet;
            delete [] TmmbrSet.ptrSsrcSet;
        }
        if(_tmmbrSetTimeouts)
        {
            delete [] _tmmbrSetTimeouts;
        }
        TmmbrSet.ptrTmmbrSet = ptrTmmbrSet;
        TmmbrSet.ptrPacketOHSet = ptrTmmbrPacketOHSet;
        TmmbrSet.ptrSsrcSet = ptrTmmbrSsrcSet;
        TmmbrSet.sizeOfSet = minimumSize;
        _tmmbrSetTimeouts = tmmbrSetTimeouts;
    }
}

void
RTCPReceiveInformation::InsertTMMBRItem(const WebRtc_UWord32 senderSSRC,
                                        const RTCPUtility::RTCPPacketRTPFBTMMBRItem& TMMBRItem)
{
    // serach to see if we have it in our list
    for(WebRtc_UWord32 i = 0; i < TmmbrSet.lengthOfSet; i++)
    {
        if(TmmbrSet.ptrSsrcSet[i] == senderSSRC)
        {
            // we already have this SSRC in our list
            // update it
            TmmbrSet.ptrPacketOHSet[i] = TMMBRItem.MeasuredOverhead;
            TmmbrSet.ptrTmmbrSet[i] = TMMBRItem.MaxTotalMediaBitRate;
            _tmmbrSetTimeouts[i] = ModuleRTPUtility::GetTimeInMS();
            return;
        }
    }
    VerifyAndAllocateTMMBRSet(TmmbrSet.lengthOfSet+1);

    const WebRtc_UWord32 idx = TmmbrSet.lengthOfSet;
    TmmbrSet.ptrPacketOHSet[idx] = TMMBRItem.MeasuredOverhead;
    TmmbrSet.ptrTmmbrSet[idx] = TMMBRItem.MaxTotalMediaBitRate;
    TmmbrSet.ptrSsrcSet[idx] = senderSSRC;
    _tmmbrSetTimeouts[idx] = ModuleRTPUtility::GetTimeInMS();
    TmmbrSet.lengthOfSet++;
}

WebRtc_Word32
RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx,
                                    const WebRtc_UWord32 targetIdx,
                                    TMMBRSet* candidateSet)
{
    if(sourceIdx >= TmmbrSet.lengthOfSet)
    {
        return -1;
    }
    if(targetIdx >= candidateSet->sizeOfSet)
    {
        return -1;
    }
    WebRtc_UWord32 timeNow = ModuleRTPUtility::GetTimeInMS();

    // use audio define since we don't know what interval the remote peer is using
    if(timeNow - _tmmbrSetTimeouts[sourceIdx] > 5*RTCP_INTERVAL_AUDIO_MS)
    {
        // value timed out
        const WebRtc_UWord32 move = TmmbrSet.lengthOfSet - (sourceIdx + 1);
        if(move > 0)
        {
            memmove(&(TmmbrSet.ptrTmmbrSet[sourceIdx]), &(TmmbrSet.ptrTmmbrSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
            memmove(&(TmmbrSet.ptrPacketOHSet[sourceIdx]),&(TmmbrSet.ptrPacketOHSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
            memmove(&(TmmbrSet.ptrSsrcSet[sourceIdx]),&(TmmbrSet.ptrSsrcSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
            memmove(&(_tmmbrSetTimeouts[sourceIdx]),&(_tmmbrSetTimeouts[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
        }
        TmmbrSet.lengthOfSet--;
        return -1;
    }

    candidateSet->ptrTmmbrSet[targetIdx] = TmmbrSet.ptrTmmbrSet[sourceIdx];
    candidateSet->ptrPacketOHSet[targetIdx] = TmmbrSet.ptrPacketOHSet[sourceIdx];
    candidateSet->ptrSsrcSet[targetIdx] = TmmbrSet.ptrSsrcSet[sourceIdx];
    return 0;
}

void RTCPReceiveInformation::VerifyAndAllocateBoundingSet(const WebRtc_UWord32 minimumSize)
{
    TmmbnBoundingSet.VerifyAndAllocateSet(minimumSize);
}
} // namespace webrtc
