#include "ofApp.h"
#include "sync.h"

static const float bpm = 120.0f; /* beats per minute */
static const int rpb = 8; /* rows per beat */
static const double row_rate = (double(bpm) / 60) * rpb;

const struct sync_track *clear_r, *clear_g, *clear_b;
const struct sync_track *cam_rot, *cam_dist;
sync_device *rocket;

static ofApp* self = NULL;

const struct sync_track *s1;
const struct sync_track *s2;
const struct sync_track *s3;
const struct sync_track *s4;
const struct sync_track *s5;
const struct sync_track *s6;
const struct sync_track *s7;
const struct sync_track *s8;
const struct sync_track *s9;

float eflip = 0.0;

#ifndef SYNC_PLAYER

static double get_row(void* p)
{
	float tt = (*self).mySound.getPositionMS()*0.001;
	return tt * row_rate;
}

static void pause(void *d, int flag)
{
	if (flag) {
		(*self).mySound.setPaused(true);

	}
	else {
		(*self).mySound.setPaused(false);
	}
}

static void set_row(void *d, int row)
{
	(*self).mySound.setPositionMS((row/row_rate)*1000.);
}

static int is_playing(void *d)
{
	return (*self).mySound.isPlaying();
}

static struct sync_cb cb = {
	pause,
	set_row,
	is_playing
};

#endif /* !defined(SYNC_PLAYER) */
//--------------------------------------------------------------
void ofApp::setup(){
    
	self = this;
    width = 1920;
    height = 1080;
    
	ofSetVerticalSync(true);
	ofSetFrameRate(60);
    ofBackground(0);
    ofDisableAlphaBlending();
    
    ofDisableArbTex();

	TuringPatternInitordie();

    noise.load("noise.png");
    noise.allocate(width, height, OF_IMAGE_COLOR);
       
	ttf.loadFont("font.ttf", 92);

	rocket = sync_create_device("sync");
#ifndef SYNC_PLAYER
	sync_connect(rocket, "localhost", SYNC_DEFAULT_PORT);
#endif

	/* get tracks */
	s1 = sync_get_track(rocket, "s1");
	s2 = sync_get_track(rocket, "s2");
	s3 = sync_get_track(rocket, "s3");
	s4 = sync_get_track(rocket, "s4");
	s5 = sync_get_track(rocket, "s5");
	s6 = sync_get_track(rocket, "s6");
	s7 = sync_get_track(rocket, "s7");
	s8 = sync_get_track(rocket, "s8");
	s9 = sync_get_track(rocket, "s9");

	mySound.load("music.mp3");
	mySound.play();
}

//--------------------------------------------------------------
void ofApp::update() {
	time = mySound.getPositionMS()*0.001;
	double row = time * row_rate;

#ifndef SYNC_PLAYER
	row = get_row(NULL);
	if (sync_update(rocket, (int)floor(row), &cb, NULL))
		sync_connect(rocket, "localhost", SYNC_DEFAULT_PORT);
#endif

	float _s1 = float(sync_get_val(s1, row));
	float _s2 = float(sync_get_val(s2, row));
	float _s3 = float(sync_get_val(s3, row));
	float _s4 = float(sync_get_val(s4, row));
	float _s5 = float(sync_get_val(s5, row));
	float _s6 = float(sync_get_val(s6, row));
	float _s7 = float(sync_get_val(s7, row));
	float _s8 = float(sync_get_val(s8, row));
	float _s9 = float(sync_get_val(s9, row));

	eflip = cos(time*2.5);

	for (int i = 0; i < 2; i++) {
			TuringPattern_A.beginS();
			if (i == 1)TuringPattern_A.update(time);
			TuringPattern_A.endS();

			Front2.beginS();
			if (i == 1)Front2.update(time);
			VMixer.setPingPongFbo("tex0", Front2.getTexture(), 0);
			Front2.endS();

			VMixer.beginS();
			VMixer.setPingPongFbo("tex0", TuringPattern_A.getTexture(), 0);
			VMixer.setPingPongFbo("tex1", Front2.getTexture(), 1);
			if (i == 1) VMixer.update(time, eflip);
			VMixer.endS();

			TuringPattern_B.beginS();
			TuringPattern_B.setPingPongFbo("tex0", VMixer.getTexture(), 0);
			if (i == 1)TuringPattern_B.update(time);
			TuringPattern_B.endS();


		TuringPattern_C.beginS();
		TuringPattern_C.setPingPongFbo("tex0", TuringPattern_B.getTexture(), 0);
		if (i == 1)TuringPattern_C.update(time);
		TuringPattern_C.endS();

		TuringPattern_D.beginS();
		TuringPattern_D.setPingPongFbo("tex0", TuringPattern_C.getTexture(), 0);
		if (i == 1)TuringPattern_D.update(time);
		TuringPattern_D.endS();

		TuringPattern.beginS();
		TuringPattern.setPingPongFbo("tex0", TuringPattern_D.getTexture(), 0);
		if (i == 1)TuringPattern.update(time);
		TuringPattern.endS();

		FrontSide.beginS();
		FrontSide.setPingPongFbo("tex0", TuringPattern.getTexture(), 0);
		FrontSide.setPingPongFbo("tex1", TuringPattern_A.getTexture(), 1);
		if (i == 1)FrontSide.update(time,_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9 );
		FrontSide.endS();

	}
	TuringPattern_A.swap();
	Front2.swap();
	VMixer.swap();
	TuringPattern_B.swap();
    TuringPattern_C.swap();
    TuringPattern_D.swap();
    TuringPattern.swap();
	FrontSide.swap();
}

//--------------------------------------------------------------
void ofApp::draw(){
    if (time <= 102.0) FrontSide.draw();
	ofSetColor(0, 0, 0, 255);

	float ss = 4.0;
	if (time > 2.0 && time < 8.0) ttf.drawStringCentered("Quadtrip - The Last Bilotrip", ofGetWidth() / 2+ss, ofGetHeight() / 2+ss);
	if (time > 82.0 && time < 86.0) ttf.drawStringCentered("code: visy + noby", ofGetWidth() / 2+ss, ofGetHeight() / 2+ss);
	if (time > 87.0 && time < 91.0) ttf.drawStringCentered("music: pumpuli", ofGetWidth() / 2+ss, ofGetHeight() / 2+ss);
	if (time > 92.0 && time < 96.0) ttf.drawStringCentered("greets: pwp dss epoch ivory labs", ofGetWidth() / 2+ss, ofGetHeight() / 2+ss);
	if (time > 98.0 && time < 102.0) ttf.drawStringCentered("Quadtrip - Vortex 2016 - BilotRIP", ofGetWidth() / 2+ss, ofGetHeight() / 2+ss);

	ofSetColor(255, 255, 255, 255);

	if (time > 2.0 && time < 8.0) ttf.drawStringCentered("Quadtrip - The Last Bilotrip", ofGetWidth() / 2, ofGetHeight() / 2);
	if (time > 82.0 && time < 86.0) ttf.drawStringCentered("code: visy + noby", ofGetWidth() / 2, ofGetHeight() / 2);
	if (time > 87.0 && time < 91.0) ttf.drawStringCentered("music: pumpuli", ofGetWidth() / 2, ofGetHeight() / 2);
	if (time > 92.0 && time < 96.0) ttf.drawStringCentered("greets: pwp dss epoch ivory labs", ofGetWidth() / 2, ofGetHeight() / 2);
	if (time > 98.0 && time < 102.0) ttf.drawStringCentered("Quadtrip - Vortex 2016 - BilotRIP", ofGetWidth() / 2, ofGetHeight() / 2);

	if (time > 102.0) std::exit(0);
}

void ofApp::TuringPatternInitordie() {
    TuringPattern.allocate(width, height);
    TuringPattern_A.allocate(width, height);
	Front2.allocate(width, height);
	VMixer.allocate(width, height);

	TuringPattern_B.allocate(width, height);
    TuringPattern_C.allocate(width, height);
    TuringPattern_D.allocate(width, height);

	FrontSide.allocate(width, height);
		 
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){
    
}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){
    
}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
    
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
    
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
    
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
    
}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
    
}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
    
}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
    
}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 
    
}
