
#include "MFSPublic.h"
#include "Rtp808Service.h"
#include "MediaClientProtocol.h"
#include "3rd/cJSON.h"
#include "AppSetting.h"

namespace mfs
{
    static bool ClearRtpBuffer(std::list<BaseWriteBuffer>& buffers, int& bufferSize)
    {
        buffers.clear();
        bufferSize = 0;
        return false;
    }

    int MediaClientProtocol::writeData(char* data, int dataLen)
    {
        int iret = preWriteData(data, dataLen);
        if (iret != 0 )
        {
            return iret;
        }
        _wirtedData += dataLen+12;
        
        uint32_t dataSize = swapBigEndian(dataLen);
        iovec datas[4] = {{(void*)zwkj_Client_Head, 4},{&dataSize, 4}, 
        {reinterpret_cast<uint8_t*>(data), static_cast<size_t>(dataLen)}
        ,{(void*)zwkj_Client_Tail, 4}};
        if (_cacheTestData.is_open())
        {
           _cacheTestData.write((const char*)zwkj_Client_Head, 4);
           _cacheTestData.write((const char*)&dataSize, 4);
           _cacheTestData.write((const char*)data, dataLen);
           _cacheTestData.write((const char*)zwkj_Client_Tail, 4);
           _cacheTestData.flush();
        }
        
        int result = BaseProtocol::WriteV(datas, 4);
        if (result == -3)
        {
            // 不是回放就跳帧
            if (!_isPlayback)
            {
                std::stringstream ss;
                ss << _serviceName <<"> WriteV buffer is full, data len: " << (dataLen+4) << ", buffer size: " << _writeBufferSize;
                logd(ss.str());
                ClearRtpBuffer(_listWriteBuffer,_writeBufferSize);
            }
        }
        _packageNumber++;
        return result;
    };

    int MediaClientProtocol::parseWebSocketHead()
    {
        if (_readParam.second<sizeof(uint32_t))
        {
            return -2;
        }
        uint32_t dataSize = *((uint32_t*)_readParam.first.data());
        dataSize = mfs::swapBigEndian(dataSize);
        if (_readParam.second<dataSize)
        {
            return -2;
        }
        _currentDataLen = dataSize;
        return 0;
    }
    int MediaClientProtocol::parseWebSocketBody()
    {
        uint8_t* payloadData = _readParam.first.data()+(sizeof(uint32_t));

        if (_currentDataLen>2)
        {
            std::string strMessage(_currentDataLen, 0);
            memcpy(strMessage.data(), payloadData, _currentDataLen);
            onMessage(strMessage);
            // onRtpData(payloadData, _currentDataLen);
        }
        
        
        int lastOffset = _readParam.second - _currentDataLen-sizeof(uint32_t);
        if(lastOffset > 0)
        {
            memcpy(_readParam.first.data(), _readParam.first.data() + _readParam.second - lastOffset, lastOffset);
        }
        _readParam.second = lastOffset;
        return 0;
    }
    int MediaClientProtocol::parse(int length)
    {
        int parseResult = 0;
        do
        {
            parseResult = parseWebSocketHead();
            // logd("parseResult="+parseResult);
            if(parseResult==0&&parseWebSocketBody() != 0)
            {
                break;
            }
            if (_readParam.second<=0)
            {
                break;
            }
        } while(parseResult == 0);//
        FORWORT_ASSERT_RETURN(parseResult != -1);
        return 0;
    }

    int MediaClientProtocol::sendHandShakeData()
    {
        _status = SEND_HANDSHAKE;
        return 0;
    }
    int MediaClientProtocol::recvHandShakeData()
    {
        _status = PARSE_HEAD_COMPLETED;
        return 0;
    }

    void MediaClientProtocol::sendMessage(const char* data, int dataLen)
    {
        int dataSize=0;
        auto sendData = Rtp808FrameParser::encodeMessage(data, dataSize);
        auto ptrdata = sendData.get();

        int result = 0;
        uint32_t jsonSize = dataSize;
        jsonSize = swapBigEndian(jsonSize);
        iovec datas[4] = {{(void*)zwkj_Client_Head, 4},{&jsonSize, static_cast<size_t>(sizeof(uint32_t))}, 
        {ptrdata, static_cast<size_t>(dataSize)}
        ,{(void*)zwkj_Client_Tail, 4}};
        result = BaseProtocol::WriteV(datas, 4, true);
    }
    
    void MediaClientProtocol::generatePackageHead(int dataLen, char* headBuf, int& headLen)
    {
        uint32_t dataSize = swapBigEndian(dataLen);
        memcpy(headBuf, zwkj_Client_Head, 4);
        memcpy(headBuf+4, &dataSize, 4);
        headLen = 8;
        _wirtedData += dataLen+12;
    }
    
    void MediaClientProtocol::generatePackageTail(int dataLen, char* tail, int& tailLen)
    {
        memcpy(tail, zwkj_Client_Head, 4);
        tailLen = 4;
    }
}