#include <iostream>

#include "player.h"
#include "transceiver.h"
#include "setup.h"

#include <vdr/tools.h>
#include <vdr/ringbuffer.h>

#include "tools.h"
#include "csocket.h"
#include "cfile.h"
#include "cselect.h"
#include "cshared.h"
#include "clist.h"

#define VIDBUFFER 2048
#define TEMPBUFFER 64
#define PESSIZE 64
#define MAX_PES_SIZE KILOBYTE(PESSIZE)
#define VIDEOBUFSIZE KILOBYTE(VIDBUFFER+PESSIZE)
#define BUFSIZE KILOBYTE(TEMPBUFFER)

using namespace std;

//#define DEBUG_STREAMC

// Global variables that control the overall behaviour

cClusterPlayer::cClusterPlayer(const char *Filename):
		cPlayer(),
		m_Transceiver(Filename) {
	m_Active = false;
	m_Filename = Filename;
	m_RingBuffer = new cRingBufferFrame(VIDEOBUFSIZE);
	m_ReadFrame = NULL;
	m_PlayFrame = NULL;
}

cClusterPlayer::~cClusterPlayer() {
	Detach();
	delete m_RingBuffer;
}

void cClusterPlayer::Activate(bool On) {
	if (On)
		Start();
	else {
		cerr << "Deactivate" << endl;
		m_Active = false;
		Cancel(3);
	}
}

void cClusterPlayer::Action(void) {
	int got=0;
	const uchar *p = NULL;
	int pc = 0;
	int i = 1;
	int prebuf = 0;
	unsigned char pesbuffer[MAX_PES_SIZE*2];
	unsigned char pesheader[3];
	uchar *pes = NULL;
	uchar *buffer = 0;
	int pesc = 0;
	cFrame *readFrame = 0;
	cFrame *playFrame = 0;

	cRingBufferFrame *ringBuffer = new cRingBufferFrame(VIDEOBUFSIZE);

	isyslog("mplayercluster player thread started");
	
	m_Active = true;

	m_Transceiver.Start();

	// pes header
	pesheader[0]=0x0;
	pesheader[1]=0x0;
	pesheader[2]=0x1;
	pesheader[3]='\0';
	pes = pesbuffer;

	buffer = new uchar[BUFSIZ];

	DevicePlay();
	cPoller Poller;
	while (m_Active) {
		if (DevicePoll(Poller, 100)){
	    LOCK_THREAD;

		// read frame
		got = 0;
		if (!readFrame) {
			got = m_Transceiver.Get((char *)buffer, BUFSIZ);
		}
		for (i=0; i<got; i++)
		{
				pesbuffer[pesc++]=buffer[i];
				if (pesc > ClusterSetup.MinBufSize * 1024 && pesbuffer[pesc-3] == 0x0 &&
					pesbuffer[pesc-2] == 0x0 &&
					pesbuffer[pesc-1] == 0x1){
						// new pes-packet
						readFrame = new cFrame(pesbuffer,pesc-3,ftUnknown,0);
						pesbuffer[0]=0x0;
						pesbuffer[1]=0x0;
						pesbuffer[2]=0x1;
						pesc=3;
						if (prebuf < ClusterSetup.NumPreBufs)
						{
								prebuf++;
								/*if (prebuf == NumPreBufs){
							//	set non-blocking after having read some bytes...
							//	if it's set from the beginning, I couldn't receive anything
#ifdef DEBUG_STREAMC
									cout << "setting nonblocking mode\n";
#endif
									got = fcntl(client,F_SETFL,O_NONBLOCK);
									if (got == -1)
										printf("error: %s\n",strerror(errno));
								}*/
						}
				}
		}

		// store frame
		if (readFrame && ringBuffer->Put(readFrame))
		{
#ifdef DEBUG_STREAMC
			cout << "+\n";
#endif
			readFrame = NULL;
		}

		// Get the next frame from the buffer:
		if (!playFrame) {
			playFrame = ringBuffer->Get();
#ifdef DEBUG_STREAMC
			cout << "-\n";
#endif
			p = NULL;
			pc = 0;
		}
		// Play the frame:
		if (playFrame && prebuf == ClusterSetup.NumPreBufs) {
			if (!p) {
				p = playFrame->Data();
				pc = playFrame->Count();
			}
			if (p) {
				int w = PlayVideo(p, pc);
				if (w > 0) {
					p += w;
					pc -= w;
				}
				else if (w < 0 && FATALERRNO) {
					LOG_ERROR;
					break;
				}
			}
			if (pc == 0) {
				ringBuffer->Drop(playFrame);
				playFrame = NULL;
				p = 0;
#ifdef DEBUG_STREAMC
				cout << "|\n";
#endif
			}
		}

	} else 
			usleep(1);
	}

	m_Transceiver.Stop();

	isyslog("mplayercluster player thread ended");
}


