/*
BCF2000 management script with 14bit precision
midi inputs are stored as MSB ans LSB and update a float parameter
on float parameter update, midi values are sent back to BCF (to ensure synchronisation of values)
*/


var pan_midi_ch = script.addIntParameter("pan midi channel", "", 0);
var pan_midi={channel:pan_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.pan.pan, value: script.addFloatParameter("pan", "current pan value", 0., 0, 1) };
// var pan_value =

var tilt_midi_ch = script.addIntParameter("tilt midi channel", "", 1);
var tilt_midi={channel:tilt_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.tilt.tilt, value: script.addFloatParameter("tilt", "current tilt value", 0., 0, 1)};

var zoom_midi_ch = script.addIntParameter("zoom midi channel", "", 2);
var zoom_midi={channel:zoom_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.zoom.zoom, value:script.addFloatParameter("zoom", "current zoom value", 0., 0, 1) };

var focus_midi_ch = script.addIntParameter("focus midi channel", "", 3);
var focus_midi={channel:focus_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.focus.focus, value: script.addFloatParameter("focus", "current focus value", 0., 0, 1)};

var dimmer_midi_ch = script.addIntParameter("dimmer midi channel", "", 4);
var dimmer_midi={channel:dimmer_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.dimmer.dimmer, value: script.addFloatParameter("dimmer", "current dimmer value", 0., 0, 1)};

var zoomCam_midi_ch = script.addIntParameter("zoomCam midi channel", "", 5);
var zoomCam_midi={channel:zoomCam_midi_ch.get(), MSB:0, LSB:0, target:root.customVariables.unitValues.variables.zoomCam.zoomCam, value: script.addFloatParameter("zoomCam", "current camera zoom value", 0., 0, 1)};

function init()
{
	//myFloatParam.set(5); //The .set() function set the parameter to this value.
	//myColorParam.set([1,.5,1,1]);	//for a color parameter, you need to pass an array with 3 (RGB) or 4 (RGBA) values.
	//myP2DParam.set([1.5,-5]); // for a Point2D parameter, you need to pass 2 values (XY)
	//myP3DParam.set([1.5,2,-3]); // for a Point3D parameter, you need to pass 3 values (XYZ)
}


function bits2float(MSB, LSB){
	Value = param.get()*16383;
	MSB = Math.floor(ccValue/128);
	// MSB=Math.round(MSB);
	LSB = Math.floor(ccValue % 128);
	// MSB=Math.round(MSB);
	// LSB=Math.round(LSB);
	script.log(MSB+ " "+ LSB);
}

function updateCC(cc, value){
	if(cc==pan_midi.channel){pan_midi.MSB = value; return pan_midi;}
	if(cc==pan_midi.channel+32){pan_midi.LSB = value; return pan_midi;}
	if(cc==tilt_midi.channel){tilt_midi.MSB = value; return tilt_midi;}
	if(cc==tilt_midi.channel+32){tilt_midi.LSB = value; return tilt_midi;}
	if(cc==zoom_midi.channel){zoom_midi.MSB = value; return zoom_midi;}
	if(cc==zoom_midi.channel+32){zoom_midi.LSB = value; return zoom_midi;}
	if(cc==focus_midi.channel){focus_midi.MSB = value; return focus_midi;}
	if(cc==focus_midi.channel+32){focus_midi.LSB = value; return focus_midi;}
	if(cc==dimmer_midi.channel){dimmer_midi.MSB = value; return dimmer_midi;}
	if(cc==dimmer_midi.channel+32){dimmer_midi.LSB = value; return dimmer_midi;}
	if(cc==zoomCam_midi.channel){zoomCam_midi.MSB = value; return zoomCam_midi;}
	if(cc==zoomCam_midi.channel+32){zoomCam_midi.LSB = value; return zoomCam_midi;}
	else return 0;
}

function updateFloat(channel){
	channel.value.set((channel.MSB*128+channel.LSB)/16383.);
}

function feedbackMidi(channel){
	channel.MSB = Math.round(Math.floor(channel.value.get()*16383. /128));
	channel.LSB = Math.round(Math.floor(channel.value.get()*16383. %128));
	script.log(channel.MSB + "  " + channel.LSB);
	local.sendCC(1, channel.channel, channel.MSB);
	local.sendCC(1, channel.channel+32, channel.LSB);
}

// function updateAxe(axe, CC, value){
// 	if(CC==axe.channel){
// 		axe.MSB = value;
// 		// root.customVariables.unitValues.variables.pan.pan.set((128*axe.MSB+axe.LSB)/16383.0);
// 	}
// 	if(CC==axe.channel+32){
// 		axe.LSB = value;
// 		// myFloatParam.set((128*MSB+LSB)/16383.0);
// 	}
// 	axe.target=(128*axe.MSB+axe.LSB)/16383.0;
// 	script.log(axe.target);
// }

function scriptParameterChanged(param)
{
	if (param.is(pan_midi.value) ){feedbackMidi(pan_midi);}
	if (param.is(tilt_midi.value) ){feedbackMidi(tilt_midi);}
	if (param.is(zoom_midi.value) ){feedbackMidi(zoom_midi);}
	if (param.is(focus_midi.value) ){feedbackMidi(focus_midi);}
	if (param.is(dimmer_midi.value) ){feedbackMidi(dimmer_midi);}
	if (param.is(zoomCam_midi.value) ){feedbackMidi(zoomCam_midi);}
	if (param.is(pan_midi_ch)){pan_midi.channel = pan_midi_ch.get();}
	if (param.is(tilt_midi_ch)){tilt_midi.channel = tilt_midi_ch.get();}
	if (param.is(zoom_midi_ch)){zoom_midi.channel = zoom_midi_ch.get();}
	if (param.is(focus_midi_ch)){focus_midi.channel = focus_midi_ch.get();}
	if (param.is(dimmer_midi_ch)){dimmer_midi.channel = dimmer_midi_ch.get();}
	if (param.is(zoomCam_midi_ch)){zoomCam_midi.channel = zoomCam_midi_ch.get();}
	//You can use the script.log() function to show an information inside the logger panel. To be able to actuallt see it in the logger panel, you will have to turn on "Log" on this script.
	// script.log("Parameter changed : "+param.name); //All parameters have "name" property
	// if(param.is(myTrigger)) script.log("Trigger !"); //You can check if two variables are the reference to the same parameter or object with the method .is()
	// else if(param.is(myEnumParam)) script.log("Label = "+param.get()+", data = "+param.getData()); //The enum parameter has a special function getData() to get the data associated to the option
	// else script.log("Value is "+param.get()); //All parameters have a get() method that will return their value
	// if (param.name == "myFloatParam"){
	// 	script.log("sending back");
	// 	var ccValue = param.get()*16383;
	// 	MSB = Math.floor(ccValue/128);
	// 	// MSB=Math.round(MSB);
	// 	LSB = Math.floor(ccValue % 128);
	// 	// MSB=Math.round(MSB);
	// 	// LSB=Math.round(LSB);
	// 	script.log(MSB+ " "+ LSB);
	// 	local.sendCC(channel, 0, MSB);
	// 	local.sendCC(channel, 32, LSB);
	//
	// }
}

/*
 This function, if you declare it, will launch a timer at 50hz, calling this method on each tick
*/
/*
function update(deltaTime)
{
	script.log("Update : "+util.getTime()+", delta = "+deltaTime); //deltaTime is the time between now and last update() call, util.getTime() will give you a timestamp relative to either the launch time of the software, or the start of the computer.
}
*/



/* ********** MODULE SPECIFIC SCRIPTING **********************

	The "local" variable refers to the object containing the scripts. In this case, the local variable refers to the module.
	It means that you can access any control inside  this module by accessing it through its address.
	For instance, if the module has a float value named "Density", you can access it via local.values.density
	Then you can retrieve its value using local.values.density.get() and change its value using local.values.density.set()
*/

/*
 This function will be called each time a parameter of this module has changed, meaning a parameter or trigger inside the "Parameters" panel of this module
 This function only exists because the script is in a module
*/
function moduleParameterChanged(param)
{
	// if(param.isParameter())
	// {
	// 	script.log("Module parameter changed : "+param.name+" > "+param.get());
	// }else
	// {
	// 	script.log("Module parameter triggered : "+value.name);
	// }

}

/*
 This function will be called each time a value of this module has changed, meaning a parameter or trigger inside the "Values" panel of this module
 This function only exists because the script is in a module
*/
function moduleValueChanged(value)
{
	// if(value.isParameter())
	// {
	// 	script.log("Module value changed : "+value.name+" > "+value.get());
	// }else
	// {
	// 	script.log("Module value triggered : "+value.name);
	// }
}

/* ********** MIDI MODULE SPECIFIC SCRIPTING ********************* */
/*

MIDI Modules have specific methods that can be used to send MIDI events such as noteOn, noteOff, controlChange and sysEx messages from Script.
If you want to send a MIDI event from this script, you can do the following :

local.sendNoteOn(1, 12, 127); //This will send a NoteOn Event on channel 1, pitch 12, velocity 127
local.sendNoteOff(1, 12); //This will send a NoteOff Event on chanenl 1, pitch 12
local.sendCC(3, 20, 65); //This will send a ControlChange on channel 3, number 20, value 65
local.sendSysEx(15,20,115,10); //This will send 4 bytes as a SysEx message
local.sendSysEx(15,20,115,10); //This will send 4 bytes as a SysEx message
*/

/*
You can intercept MIDI Events with the functions below
*/

function noteOnEvent(channel, pitch, velocity)
{
	script.log("Note on received "+channel+", "+pitch+", "+velocity);
}


function noteOffEvent(channel, pitch, velocity)
{
	script.log("Note off received "+channel+", "+pitch+", "+velocity);
}

function ccEvent(channel, number, value)
{

	var ccChannel = updateCC(number, value); //return axe.MSB or axe.LSB
	if (ccChannel){updateFloat(ccChannel);}
	// ccChannel.set(value);

	// script.log("hello");

	// script.log("ControlChange received "+channel+", "+number+", "+value);
	// //feedback to BCF
	// // local.sendCC(channel, number, value);
	// if(number==pan_midi_ch){
	// 	MSB = value;
	// 	myFloatParam.set((128*MSB+LSB)/16384.0);
	// }
	// if(number==32){
	// 	LSB = value;
	// 	myFloatParam.set((128*MSB+LSB)/16384.0);
	// }
}

function sysExEvent(data)
{
	script.log("Sysex Message received, "+data.length+" bytes :");
	for(var i=0; i < data.length; i++)
	{
		script.log(" > "+data[i]);
	}
}
