/*
 *  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.
 */

// BWEStandAlone.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <string>

#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/system_wrappers/include/event_wrapper.h"
#include "webrtc/system_wrappers/include/trace.h"
#include "webrtc/test/channel_transport/udp_transport.h"

#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h"
#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h"

#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h"

//#include "vld.h"

class myTransportCB: public UdpTransportData
{
public:
    myTransportCB (RtpRtcp *rtpMod) : _rtpMod(rtpMod) {};
protected:
    // Inherited from UdpTransportData
 void IncomingRTPPacket(const int8_t* incomingRtpPacket,
                        const size_t rtpPacketLength,
                        const int8_t* fromIP,
                        const uint16_t fromPort) override;

 void IncomingRTCPPacket(const int8_t* incomingRtcpPacket,
                         const size_t rtcpPacketLength,
                         const int8_t* fromIP,
                         const uint16_t fromPort) override;

private:
    RtpRtcp *_rtpMod;
};

void myTransportCB::IncomingRTPPacket(const int8_t* incomingRtpPacket,
                                      const size_t rtpPacketLength,
                                      const int8_t* fromIP,
                                      const uint16_t fromPort)
{
    printf("Receiving RTP from IP %s, port %u\n", fromIP, fromPort);
    _rtpMod->IncomingPacket((uint8_t *) incomingRtpPacket, rtpPacketLength);
}

void myTransportCB::IncomingRTCPPacket(const int8_t* incomingRtcpPacket,
                                       const size_t rtcpPacketLength,
                                       const int8_t* fromIP,
                                       const uint16_t fromPort)
{
    printf("Receiving RTCP from IP %s, port %u\n", fromIP, fromPort);
    _rtpMod->IncomingPacket((uint8_t *) incomingRtcpPacket, rtcpPacketLength);
}


int main(int argc, char* argv[])
{
    bool isSender = false;
    bool isReceiver = false;
    uint16_t port;
    std::string ip;
    TestSenderReceiver *sendrec = new TestSenderReceiver();
    TestLoadGenerator *gen;

    if (argc == 2)
    {
        // receiver only
        isReceiver = true;

        // read port
        port = atoi(argv[1]);
    }
    else if (argc == 3)
    {
        // sender and receiver
        isSender = true;
        isReceiver = true;

        // read IP
        ip = argv[1];

        // read port
        port = atoi(argv[2]);
    }

    Trace::CreateTrace();
    Trace::SetTraceFile("BWEStandAloneTrace.txt");
    Trace::set_level_filter(webrtc::kTraceAll);

    sendrec->InitReceiver(port);

    sendrec->Start();

    if (isSender)
    {
        const uint32_t startRateKbps = 1000;
        //gen = new CBRGenerator(sendrec, 1000, 500);
        gen = new CBRFixFRGenerator(sendrec, startRateKbps, 90000, 30, 0.2);
        //gen = new PeriodicKeyFixFRGenerator(sendrec, startRateKbps, 90000, 30, 0.2, 7, 300);
        //const uint16_t numFrameRates = 5;
        //const uint8_t frameRates[numFrameRates] = {30, 15, 20, 23, 25};
        //gen = new CBRVarFRGenerator(sendrec, 1000, frameRates, numFrameRates, 90000, 4.0, 0.1, 0.2);
        //gen = new CBRFrameDropGenerator(sendrec, startRateKbps, 90000, 0.2);
        sendrec->SetLoadGenerator(gen);
        sendrec->InitSender(startRateKbps, ip.c_str(), port);
        gen->Start();
    }

    while (1)
    {
    }

    if (isSender)
    {
        gen->Stop();
        delete gen;
    }

    delete sendrec;

    //uint8_t numberOfSocketThreads = 1;
    //UdpTransport* transport = UdpTransport::Create(0, numberOfSocketThreads);

    //RtpRtcp* rtp = RtpRtcp::CreateRtpRtcp(1, false);
    //if (rtp->InitSender() != 0)
    //{
    //    exit(1);
    //}
    //if (rtp->RegisterSendTransport(transport) != 0)
    //{
    //    exit(1);
    //}

//    transport->InitializeSendSockets("192.168.200.39", 8000);
    //transport->InitializeSendSockets("127.0.0.1", 10000);
    //transport->InitializeSourcePorts(8000);


    return(0);
 //   myTransportCB *tp = new myTransportCB(rtp);
 //   transport->InitializeReceiveSockets(tp, 10000, "0.0.0.0");
 //   transport->StartReceiving(500);

 //   int8_t data[100];
 //   for (int i = 0; i < 100; data[i] = i++);

 //   for (int i = 0; i < 100; i++)
 //   {
 //       transport->SendRaw(data, 100, false);
 //   }



 //   int32_t totTime = 0;
 //   while (totTime < 10000)
 //   {
 //       transport->Process();
 //       int32_t wTime = transport->TimeUntilNextProcess();
 //       totTime += wTime;
 //       Sleep(wTime);
 //   }


    //if (transport)
    //{
    //    // Destroy the Socket Transport module
    //    transport->StopReceiving();
    //    transport->InitializeReceiveSockets(NULL,0);// deregister callback
 //       UdpTransport::Destroy(transport);
    //    transport = NULL;
 //   }

 //   if (tp)
 //   {
 //       delete tp;
 //       tp = NULL;
 //   }

 //   if (rtp)
 //   {
 //       RtpRtcp::DestroyRtpRtcp(rtp);
 //       rtp = NULL;
 //   }


    //return 0;
}
