//*******************************************************************************
//*  Copyright (c) Federal University of Para, Brazil - 2012			*
//*  Developed at the Research Group on Computer Network and Multimedia		*
//*  Communication (GERCOM)							*
//*  All rights reserved							*
//*										*
//*  Permission to use, copy, modify, and distribute this protocol and its	*
//*  documentation for any purpose, without fee, and without written		*
//*  agreement is hereby granted, provided that the above copyright notice,	*
//*  and the author appear in all copies of this protocol.			*
//*										*
//*  Version:  0.1								*
//*  Author(s): Denis do Rosário <denis@ufpa.br>				*
//*										*
//******************************************************************************/

#include "VideoApp.h"
#include "WiseDebug.h"

Define_Module(VideoApp);

VideoApp::VideoApp() {
}

VideoApp::~VideoApp() {
}

void VideoApp::initialize() {
    WiseBaseApplication::initialize();
    isSink = par("isSink");
    idVideo = -1;

    if (self == 1)
	setTimer(REQUEST_MULTIMEDIA, 3.1);
}

void VideoApp::finish() {
    WiseBaseApplication::finish();
    crtlIterator = set.begin();
    while(crtlIterator != set.end()){
	video cls  = *crtlIterator;				
        fclose(cls.pFile);		
	crtlIterator = set.erase(crtlIterator);
    }
    cOwnedObject *Del=NULL;
    int OwnedSize = this->defaultListSize();
    for(int i=0; i<OwnedSize; i++){
	Del = this->defaultListGet(0);
	this->drop(Del);
	delete Del;
    }
}

void VideoApp::timerFiredCallback(int index){
    switch (index) {
        case REQUEST_MULTIMEDIA:{
	    idVideo ++;
	    WiseApplicationPacket* m = new WiseApplicationPacket("request multimedia", SENSOR_READING_MESSAGE);
	    m->setIdNode(self);
	    m->setIdVideo(idVideo);
            send(m, "toSensorDeviceManager");
	    setTimer(REQUEST_MULTIMEDIA, 20);
	    break;
	}
    }
}

void VideoApp::AddReceivedTrace (double time, bool generateTrace, TraceInfo tParam) {
	if (generateTrace){
		if(set.empty()){
    	    		writeRdTrace(tParam.nodeId,tParam.seqNum);
    	    	} 		        
	    	for (crtlIterator = set.begin(); crtlIterator != set.end(); crtlIterator++){
			video info = *crtlIterator;
		    	/*
	    	     	 * Test if the output file is already created
	    	     	 * If the packtes is for the current seq number save the frame on the output file
	    	     	 * else close the file and create the new output file with the new seq number
	    	    	*/
	    	    	if (tParam.nodeId == info.ch && tParam.seqNum == info.sn){
		    		fprintf(info.pFile, "%f             id %d            udp %d\n",time, tParam.id, tParam.byteLength);
				//trace() << "Frame " << tParam.id << " added";
	    	    	} else if (tParam.nodeId != info.ch || tParam.seqNum != info.sn){
    	               		fclose(info.pFile);
	            		crtlIterator = set.erase(crtlIterator);
	            		writeRdTrace(tParam.nodeId, tParam.seqNum);
	        	}
	    	}
	}
}

void VideoApp::handleMobilityControlMessage(MobilityManagerMessage* pkt) {
}

void VideoApp::fromNetworkLayer(cPacket* msg, const char* src, double rssi, double lqi) {
    switch (msg->getKind()) {
	case MULTIMEDIA_PACKET:{
	    WiseApplicationPacket *rcvPackets = check_and_cast<WiseApplicationPacket*>(msg);
	    TraceInfo tParam = rcvPackets->getInfo();
	    AddReceivedTrace (SIMTIME_DBL(simTime()), true, tParam);
	    break;
	}
    }
}

/*
 * Create the output file and save it in a list
*/
void VideoApp::writeRdTrace(int id,int seqNum){
    char fileTrace[50];
    sprintf(fileTrace,"rd_sn_%i_ch_%i", seqNum,id);
    video temp;
    temp.ch = id;
    temp.sn = seqNum;
    temp.pFile = fopen(fileTrace, "a+");
    set.push_back(temp);
}

void VideoApp::handleSensorReading(WiseSensorMessage* msg) {
    int msgKind = msg->getKind();
    switch (msgKind) {
        case MULTIMEDIA:{
	    WiseApplicationPacket *pktTrace = new WiseApplicationPacket("SENDING MULTIMEDIA DATA", MULTIMEDIA_PACKET);
	    pktTrace->setByteLength(msg->getByteLength());
	    pktTrace->setTypeFrame(msg->getTypeFrame());
	    pktTrace->setIdFrame(msg->getIdFrame());
	    pktTrace->setInfo(msg->getInfo());
    	    toNetworkLayer(pktTrace, BROADCAST_NETWORK_ADDRESS);

	    break;
	}
    }
}

void VideoApp::handleDirectApplicationMessage(WiseApplicationPacket* pkt) {
     //trace() << "direct app msg";
}
