#include "videoLineModule.h"

// static video stuff here:
static int 					numPlayers = 3;
static ofVideoPlayer		videoPlayers[3];
static int 					videoCounter = 0;	
static bool 				bTexAllocated = false;
static lineTexture			videoTexture[3];
static unsigned char 		* black;

#ifdef TARGET_OSX

void * thread(void *vlmPtr){
		videoLineModule* me	= (videoLineModule*)vlmPtr;
		printf("checking name is %s \n", me->movieName);	
		me->loadIntoMoviePlayer();
		printf("we should be here\n");	
		
}

#else

//-----------------------------------
// sorry theo - 
#include <process.h>
unsigned int __stdcall thread(void *vlmPtr) {
	videoLineModule* me	= (videoLineModule*)vlmPtr;
	me->loadIntoMoviePlayer();
	return 0;
}

#endif


//-------------------------------------------
videoLineModule::videoLineModule(){
	
	setup();
	
	bPointNew = false;
	myVideoPlayer = 0;
	
	// ok ,the deal is this - we will load the films in a thread
	// and we can't allocate texture in a thread (opengl is not thread safe)
	// so we will use our own textures:
	for (int i = 0; i < 3; i++){
		videoPlayers[i].setUseTexture(false);
	}
	
	// make 3 static textures:
	if (!bTexAllocated){
		for (int i = 0; i < 3; i++){
			videoTexture[i].allocate(640,480, GL_RGB); // I don't think we will have bigger videos then this...
		}
		bTexAllocated = true;
	}
	
	black = new unsigned char[640*480*3];
	
	bScrubbing 	= false;
	scrubSpeed 	= 0.005f;
	movieSpeed 	= 1.0f;
	volume 		= 0;
}

//-------------------------------------------	
void videoLineModule::setMovie(char * movieNameStr){
	
	sprintf(movieName, "%s", movieNameStr);
	sprintf(path, "../../../settings/%s.xml", movieName);
	
	ts.loadSettings(path);
	box->setStartPointAngle(ts.getStartingPoint(), ts.getStartingAngle());
	
}

//------------------------------------------- this is where we load the film
void videoLineModule::loadIntoMoviePlayer(){
		
	#ifdef TARGET_OSX
		int value = pthread_mutex_trylock(&myMutex);
		if(value == 0){
		printf("we are in -- mutext is now locked \n");
	#endif 
	
	sprintf(path, "../../../movies/%s", movieName);
	videoPlayers[myVideoPlayer].loadMovie(path);
	videoPlayers[myVideoPlayer].setSpeed(movieSpeed);
	videoPlayers[myVideoPlayer].setVolume(0);
	if (bScrubbing == true){
		videoPlayers[myVideoPlayer].setPosition(ts.startPct);
		videoPlayers[myVideoPlayer].play();
		
		videoPlayers[myVideoPlayer].setLoopState(OF_QT_LOOP_NONE);
		videoPlayers[myVideoPlayer].idleMovie();
	} else {
		videoPlayers[myVideoPlayer].setPosition(ts.startPct);
		videoPlayers[myVideoPlayer].play();
	}
	
	bMovieLoaded = 1;
	
	#ifdef TARGET_OSX
		
		pthread_mutex_unlock(&myMutex);
		printf("we are out -- mutext is now unlocked \n");
		
		}
		else printf("mutext is busy \n");

	#endif
	
	
}


//-------------------------------------------	
void videoLineModule::setup(){
	pct 				= 0;
	bMovieLoaded		= 0;	
}

//-------------------------------------------	
void videoLineModule::reset(){
	
	pct 				= 0;
	myVideoPlayer 		= videoCounter;
	bMovieLoaded		= 0;
	
	videoTexture[myVideoPlayer].loadData(black, 640,480, GL_RGB);
		
	#ifdef TARGET_OSX
		pthread_mutex_init(&myMutex, NULL);		
		pthread_create(&myThread, NULL, thread, (void *)this);
	#else
		myThread = (HANDLE)_beginthreadex(NULL, 0, thread,  (void *)this, 0,NULL);
	#endif	
	
	// increase the counter, so the next guy uses 
	// a different videoCounter...
	
	videoCounter++;
	videoCounter %= numPlayers;
	fadeIn = 0;
	
}
		


//-------------------------------------------	
void videoLineModule::update(){

	
	
	
	// ------------------------------- check if we've loaded every update:

	// ------------------------------- check if we've loaded every update:
	#ifdef TARGET_OSX
	if (bMovieLoaded == 1){
		int value = pthread_mutex_trylock(&myMutex);
		if(value == 0){
			bMovieLoaded = 2;
			pthread_mutex_unlock(&myMutex);
			pthread_mutex_destroy(&myMutex);
			pthread_detach(myThread);
		}else{
			;; 	// < do nothing ... this is what we wanted to avoid
		}
	}
	#else
	if (bMovieLoaded == 1){
		switch (WaitForSingleObject(myThread, 1)){
			case WAIT_OBJECT_0:
				bMovieLoaded = 2;
				CloseHandle(myThread);
	    		break;
	    
			case WAIT_TIMEOUT:
				;; 	// < do nothing ... this is what we wanted to avoid
		 		break;
	    }
    }
    #endif
	
    // ------------------------------- ok we are in:
    if (bMovieLoaded == 2){ 
	   		
	   		videoPlayers[myVideoPlayer].idleMovie();
			
			if (bScrubbing != true){
				pct = videoPlayers[myVideoPlayer].getPosition();
				videoPlayers[myVideoPlayer].setSpeed(movieSpeed);
	
			} else {
				pct += scrubSpeed;
			}
			//
			if (pct > 0 && pct < 1){
				if (bScrubbing == true){
					videoPlayers[myVideoPlayer].setPaused(true);
					videoPlayers[myVideoPlayer].setPosition(pct);
				}
				ofVec3f point = ts.getPointForPct(pct);
				if ((point.x != pointPos.x)  && (point.x >= 0.0f)){
					bPointNew = true;
					pointPos.set(point);
				}
			}
			
			if (videoPlayers[myVideoPlayer].isFrameNew()){
				
				// ok a moment of honesty
				// we can prolly get this faster
				// since the memory is contiguous (for easier working with)
				// it's a bit slower then if the memory is block aligned
				// like it is in quicktime.
				// anyway, we roll:
				
				videoTexture[myVideoPlayer].loadData(
					videoPlayers[myVideoPlayer].getPixels(),
					videoPlayers[myVideoPlayer].width,
					videoPlayers[myVideoPlayer].height,GL_RGB);
				
			}
			
		
	}
	box->updatePts();
}

//-------------------------------------------	
bool videoLineModule::bHaveNewPoint(){
	return bPointNew;
}

//-------------------------------------------	
ofVec3f videoLineModule::getNewPoint(){
	bPointNew = false;
	return interpolatePt(box->ptsTranslated, pointPos.x/640.0f, 1-(pointPos.y/480.0f));
}


//-------------------------------------------	
void videoLineModule::draw(float offsetx, float offsety){
		
	// add the offset to the translation:
	ofVec3f ptsTransAndOffsetted[4];
	for (int i = 0; i < 4; i++){
		ptsTransAndOffsetted[i].set(box->ptsTranslated[i].x - offsetx, 	
									box->ptsTranslated[i].y - offsety, 0	
									);
	}

	if (bMovieLoaded == 2){
		// draw the texture:
		fadeIn = fadeIn * 0.99f + 0.01f * 1.0f;
		if (fadeIn < 0.99f){
			ofEnableAlphaBlending();
			ofSetColor(255,255,255, fadeIn*255);
			videoTexture[myVideoPlayer].draw(ptsTransAndOffsetted);
			ofDisableAlphaBlending();
		} else {
			ofSetColor(0xffffff);
			videoTexture[myVideoPlayer].draw(ptsTransAndOffsetted);
		}
	}
	
	glPushMatrix();
		ofSetColor(0xffffff);
		box->draw(offsetx, offsety);
	glPopMatrix();
	
	
}

