//Get the Medooze Media Server interface
const MediaServer = require("medooze-media-server");

//Get Semantic SDP objects
const SemanticSDP	= require("semantic-sdp");
const SDPInfo		= SemanticSDP.SDPInfo;
const MediaInfo		= SemanticSDP.MediaInfo;
const CandidateInfo	= SemanticSDP.CandidateInfo;
const DTLSInfo		= SemanticSDP.DTLSInfo;
const ICEInfo		= SemanticSDP.ICEInfo;
const StreamInfo	= SemanticSDP.StreamInfo;
const TrackInfo		= SemanticSDP.TrackInfo;
const Direction		= SemanticSDP.Direction;
const CodecInfo		= SemanticSDP.CodecInfo;

const Capabilities = {
	video : {
		codecs		: ["vp9"],
		rtx		: true,
		rtcpfbs		: [
			{ "id": "transport-cc"},
			{ "id": "ccm", "params": ["fir"]},
			{ "id": "nack"},
			{ "id": "nack", "params": ["pli"]}
		],
		extensions	: [ "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"]
	}
};

module.exports = function(request,protocol,endpoint)
{
	const connection = request.accept(protocol);

	connection.on('message', (frame) =>
	{
		//Get cmd
		var msg = JSON.parse(frame.utf8Data);

		//Get cmd
		if (msg.cmd==="OFFER")
		{
			const streams = {};

			//Process the sdp
			var offer = SDPInfo.process(msg.offer);

			//Create an DTLS ICE transport in that enpoint
			const transport = endpoint.createTransport(offer);
			
			//Enable probing
			transport.setBandwidthProbing(true);
			transport.setMaxProbingBitrate(512000);
			
			//DUMP
			//transport.dump("recordings/svc-"+ts+".pcap",{incoming:true,rtcp:true,rtpHeadersOnly:true,bwe:true});

			//Set RTP remote properties
			 transport.setRemoteProperties({
				audio : offer.getMedia("audio"),
				video : offer.getMedia("video")
			});

			//Create local SDP info
			const answer = offer.answer({
				dtls		: transport.getLocalDTLSInfo(),
				ice		: transport.getLocalICEInfo(),
				candidates	: endpoint.getLocalCandidates(),
				capabilities	: Capabilities
			});

			//Set RTP local  properties
			transport.setLocalProperties({
				video : answer.getMedia("video")
			});
			
			//Get offered stream info
			const offered = offer.getFirstStream();
			
			//Create the remote stream into the transports
			const incomingStream = transport.createIncomingStream(offered);

			//Create new local stream
			const outgoingStream  = transport.createOutgoingStream({
				audio: false,
				video: true
			});

			//Get local stream info
			const info = outgoingStream.getStreamInfo();

			//Copy incoming data from the remote stream to the local one
			const transponder = connection.transporder = outgoingStream.attachTo(incomingStream)[0];
			
			//Start on low
			transponder.selectLayer(0,0);
			
			//Listen for bwe events
			transport.on("targetbitrate",	bitrate=>{
				//Get previous layer ids
				const sid = transponder.getSelectedSpatialLayerId();
				const tid = transponder.getSelectedTemporalLayerId();
				//Select stream layer from bitrate
				const rate = transponder.setTargetBitrate(bitrate);
				//Get next layer
				const next = rate.layers[rate.layerIndex-1];
				//Probing
				let probing = false;
				//If the jump is lower
				if (next)
				{
					//Set probing bitrate
					probing = next.bitrate-rate;
					//Set it on transport
					transport.setMaxProbingBitrate(next.bitrate-rate);
					//Enable
					transport.setBandwidthProbing(true);
				} else 
					//Disable
					transport.setBandwidthProbing(false);
					
				//Log
				console.log("targetbitrate :" + bitrate + " probing:" + probing +" sid:" + transponder.getSelectedSpatialLayerId() + " tid:" +transponder.getSelectedTemporalLayerId());
				//If changed
				if (sid!=transponder.getSelectedSpatialLayerId() || tid!=transponder.getSelectedTemporalLayerId())
					//Send response
					connection.sendUTF(JSON.stringify({
						sid : transponder.getSelectedSpatialLayerId(),
						tid : transponder.getSelectedTemporalLayerId()
					}));
			});

			//Add local stream info it to the answer
			answer.addStream(info);

			//Add to streams
			streams[incomingStream.getId()] = incomingStream;

			//Send response
			connection.sendUTF(JSON.stringify({
				answer : answer.toString()
			}));

			//Close on disconnect
			connection.on("close",() => {
				//Stop
				transport.stop();
			});
		} else {
			//Select layer
			connection.transporder.selectLayer(parseInt(msg.spatialLayerId),parseInt(msg.temporalLayerId));
		}
	});
};
