#include "rtp-internal.h"
#include "rtp-packet.h"
#include "rtp-util.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//enum { 
//	RTCP_MSG_MEMBER,	/// new member(re-calculate RTCP Transmission Interval)
//	RTCP_MSG_EXPIRED,	/// member leave(re-calculate RTCP Transmission Interval)
//};

static void rtp_seq_init(struct rtp_member *sender, uint16_t seq)
{
	sender->rtp_seq = seq;
	sender->rtp_seq_bad = (1<<16) + 1; /* so seq == bad_seq is false */
	sender->rtp_seq_base = seq;
	sender->rtp_seq_cycles = 0;
	sender->rtp_packets0 = 0;
	sender->rtp_expected0 = 0;
	sender->rtp_bytes = 0;
	sender->rtp_packets = 0;
	sender->rtp_probation = 0;
	sender->jitter = 0.0;
}

static int rtp_seq_update(struct rtp_member *sender, uint16_t seq)
{
	uint16_t delta;
	delta = seq - sender->rtp_seq;

	if(sender->rtp_probation > 0)
	{
		if(sender->rtp_seq + 1 == seq)
		{
			sender->rtp_seq = seq;
			if(0 == --sender->rtp_probation)
			{
				rtp_seq_init(sender, seq);
				return 1;
			}
		}
		else
		{
			sender->rtp_probation = RTP_PROBATION;
			sender->rtp_seq = seq;
		}
		return 0;
	}
	else if( delta < RTP_DROPOUT)
	{
		// in order, with permissible gap
		if(seq < sender->rtp_seq)
		{
			// sequence number wrapped
			sender->rtp_seq_cycles += (1 << 16);
		}

		sender->rtp_seq = seq;
	}
	else if( delta <= (1 << 16) - RTP_MISORDER )
	{
		/* the sequence number made a very large jump */
		if(sender->rtp_seq_bad + 1 == seq)
		{
			rtp_seq_init(sender, seq);
		}
		else
		{
			sender->rtp_seq_bad = seq;
			return 0;
		}
	}
	else
	{
		// duplicate or reordered packet
	}

	return 1;
}

struct rtp_member* rtp_member_fetch(struct rtp_context *ctx, uint32_t ssrc)
{
	struct rtp_member *p;
	p = rtp_member_list_find(ctx->members, ssrc);
	if(!p)
	{
		// exist in sender list?
		assert(!rtp_member_list_find(ctx->senders, ssrc));

		p = rtp_member_create(ssrc);
		if(p)
		{
			struct rtcp_msg_t msg;

			// update members list
			rtp_member_list_add(ctx->members, p);
			rtp_member_release(p);

			//msg.type = RTCP_MSG_MEMBER;
			//msg.u.member.ssrc = ssrc;
			//ctx->handler.on_rtcp(ctx->cbparam, &msg);
		}
	}
	return p;
}

struct rtp_member* rtp_sender_fetch(struct rtp_context *ctx, uint32_t ssrc)
{
	struct rtp_member *p;
	p = rtp_member_list_find(ctx->senders, ssrc);
	if(!p)
	{
		p = rtp_member_fetch(ctx, ssrc);
		if(p)
		{
			// update senders list
			rtp_member_list_add(ctx->senders, p);
		}
	}
	return p;
}

static int rtcp_parse(struct rtp_context *ctx, const unsigned char* data, size_t bytes)
{
	int n;
	uint32_t rtcphd;
	rtcp_header_t header;

	assert(bytes >= sizeof(rtcphd));
	rtcphd = nbo_r32(data);

	header.v = RTCP_V(rtcphd);
	header.p = RTCP_P(rtcphd);
	header.rc = RTCP_RC(rtcphd);
	header.pt = RTCP_PT(rtcphd);
	header.length = RTCP_LEN(rtcphd);
	n = header.length * 4 + 4;

	// 1. RTP version field must equal 2 (p69)
	// 2. The payload type filed of the first RTCP packet in a compound packet must be SR or RR (p69)
	// 3. padding only valid at the last packet
	if (n > bytes || 2 != header.v || (header.p && (header.length < 1 || header.length * 4 < data[n - 1])))
	{
		assert(0);
		return -1;
	}

	if(header.p)
		n -= data[n - 1];

	switch(header.pt)
	{
	case RTCP_SR:
		rtcp_sr_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_RR:
		rtcp_rr_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_SDES:
		rtcp_sdes_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_BYE:
		rtcp_bye_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_APP:
		rtcp_app_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_RTPFB:
		rtcp_rtpfb_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_PSFB:
		rtcp_psfb_unpack(ctx, &header, data + 4, n - 4);
		break;

	case RTCP_XR:
		rtcp_xr_unpack(ctx, &header, data + 4, n - 4);
		break;

	default:
		assert(0);
	}

	return (RTCP_LEN(rtcphd) + 1) * 4;
}

int rtcp_input_rtcp(struct rtp_context *ctx, const void* data, int bytes)
{
	int r;
	const unsigned char* p;

	// RFC3550 6.1 RTCP Packet Format
	// 1. The first RTCP packet in the compound packet must always be a report packet to facilitate header validation
	// 2. An SDES packet containing a CNAME item must be included in each compound RTCP packet
	// 3. BYE should be the last packet sent with a given SSRC/CSRC.
	p = (const unsigned char*)data;
	while(bytes > 4)
	{
		// compound RTCP packet
		r = rtcp_parse(ctx, p, bytes);
		if(r <= 0)
			break;

		// RFC3550 6.3.3 Receiving an RTP or Non-BYE RTCP Packet (p26)
		ctx->avg_rtcp_size = (int)(ctx->avg_rtcp_size*1.0/16 + r * 15.0/16);

		p += r;
		bytes -= r;
	}
	return 0;
}

int rtcp_input_rtp(struct rtp_context *ctx, const void* data, int bytes)
{
	uint64_t clock;
	struct rtp_packet_t pkt;
	struct rtp_member *sender;

	if(0 != rtp_packet_deserialize(&pkt, data, bytes))
		return -1; // packet error

	assert(2 == pkt.rtp.v);
	sender = rtp_sender_fetch(ctx, pkt.rtp.ssrc);
	if(!sender)
		return -1; // memory error

	clock = rtpclock();

	// RFC3550 A.1 RTP Data Header Validity Checks
	if(0 == rtp_seq_update(sender, (uint16_t)pkt.rtp.seq))
		return 0; // disorder(need more data)

	// RFC3550 A.8 Estimating the Interarrival Jitter
	// the jitter estimate is updated:
	if(0 != sender->rtp_packets)
	{
		int D;
		D = (int)((unsigned int)((clock - sender->rtp_clock)*ctx->frequence/1000000) - (pkt.rtp.timestamp - sender->rtp_timestamp));
		if(D < 0) D = -D;
		sender->jitter += (D - sender->jitter)/16.0;
	}
	else
	{
		sender->jitter = 0.0;
	}

	sender->rtp_clock = clock;
	sender->rtp_timestamp = pkt.rtp.timestamp;
	sender->rtp_bytes += pkt.payloadlen;
	sender->rtp_packets += 1;
	return 1;
}
