text: "use strict";
  
  //var m = require('../controle.js');//not sure it is needed to add the requester to share variables
  var Beagle = require('beaglebone-io');
  var b = new Beagle();
  var debug = require('debug')('gpio');
  
  //Variables
  var led = module.exports.led = new PinObjectIO("USR1");
  var mash_pump = module.exports.mash_pump = new PinObjectIO("P8_12");//P8_12
  var boil_pump = module.exports.boil_pump = new PinObjectIO("P8_10");//P8_10
  var pumps = module.exports.pumps = {mash_pump:mash_pump, boil_pump:boil_pump};
  
  var mash_valve = module.exports.mash_valve = new PinObjectIO("P8_08");//P8_08
  var boil_valve = module.exports.boil_valve = new PinObjectIO("P8_09");//P8_09
  var chill_valve = module.exports.chill_valve = new PinObjectIO("P8_07");//P8_07
  var water_valve = module.exports.water_valve = new PinObjectIO("P8_11");//P8_11
  var valves = module.exports.valves = {	mash_valve:mash_valve, boil_valve:boil_valve,
  				chill_valve:chill_valve, water_valve:water_valve};
  
  var mash_heat = module.exports.mash_heat = new PinObjectIO("P8_13");
  var boil_heat = module.exports.boil_heat = new PinObjectIO("P8_14");
  var heaters = module.exports.heaters = {mash_heat:mash_heat, boil_heat:boil_heat};
  
  		//for servo, use 0.0325 < duty < 0.11 to protect servo integrity
  var servo_pwm = module.exports.servo_pwm = {id:"P8_19", state:{duty:0.0325, freq:50}, cfg:b.ANALOG_OUTPUT};//state of PWM is duty-cycle and frequency
  //var servo_pwm = {id:"P8_19", state:{duty:0.11, freq:60}};//this is for the SSR test
  
  var all_io = module.exports.all_io = collect(pumps,valves,heaters,{led:led},{servo_pwm:servo_pwm});
  //debug(all_io);
  var all_io_objects = module.exports.all_io_objects = Object.keys(all_io);//get all the keys, because cannot access object by index, e.g all_io[2]
  var all_io_pins = module.exports.all_io_pins = [];//all the pins used as an array
  for (var i = 0; i < all_io_objects.length; i++){//get the pins one by one
  	all_io_pins[i] = all_io[all_io_objects[i]].id;//and add to the array
  }
  
  var ioStatus = module.exports.ioStatus = {cfgok:0, gpio:0, pwm:0, analog:0, interrupt:0, total:all_io_objects.length, //helping object
  				//some functions just to exercise the use of methods
  				newGpio:		function(){	this.cfgok++; this.gpio++;},
  				newPwm:			function(){	this.cfgok++; this.pwm++;},
  				newAnalog:		function(){	this.cfgok++; this.analog++;},
  				newInterrupt:	function(){	this.cfgok++; this.analog++;},
  				gpio2pwm:		function(){ this.gpio--; this.pwm++;},
  				gpio2interrupt:	function(){ this.gpio--; this.interrupt++;},
  				pwm2gpio:		function(){ this.pwm--; this.gpio++;},
  				pwm2interrupt:	function(){ this.pwm--; this.interrupt++;},
  				interrupt2gpio:	function(){ this.interrupt--; this.gpio++;},
  				interrupt2pwm:	function(){ this.interrupt--; this.pwm++;}
  };
  
  //functions
  module.exports.changeStatusIO = function (pin, val){
  	if(val == "true"){//if button is checked
  		all_io[pin].state = b.HIGH;//turn corresponding pin HIGH
  		b.digitalWriteSync(all_io[pin].id, all_io[pin].state);
  		debug("Pin " + pin + " turned HIGH");
  	}
  	else if(val == "false"){//if button is unchecked
  		all_io[pin].state = b.LOW;//turn corresponding pin LOW
  		b.digitalWriteSync(all_io[pin].id, all_io[pin].state);
  		debug("Pin " + pin + " turned LOW");
  	}
  	else{//if it is not a button
  		if(pin == "servo_pwm"){//check if this is the PWM
  			servo_pwm.state.duty = 0.0325 + (0.0775/180)*val;//turn degree to duty-cycle
  			b.analogWrite(servo_pwm.id,servo_pwm.state.duty,servo_pwm.state.freq, function(err_wr){//set PWM
  				if(err_wr){//if anything goes wrong
  					debug(err_wr);//print the error
  				}
  				else{//otherwise
  					debug("Servo angle set to: " + val);//print the angle the PWM was set to
  				}
  			});
  		}
  	}
  };
  
  module.exports.getSystemStatus = function (){
  	var all_io_status = {};//object with all the pin pairs key:value
  	for(var i = 0; i < all_io_objects.length; i++){//get the pair key:value pin by pin
  		all_io_status[all_io_objects[i]] = all_io[all_io_objects[i]].state;
  	}
  	return(all_io_status);
  };
  
  // I/O pins
  function PinObjectIO(pinId){//function to create pin object, should recieve pin ID
  	if(pinId){//if the variable is passed to function or not empty
  		this.id = pinId; this.state = b.LOW; this.cfg = b.OUTPUT;
  	}
  	else{//if no variable is passed or passed empty
  		debug("No variable passed to create pin object");
  	}
  }
  
  module.exports.pinsConfiguration = function (){
  	for (var i = 0; i < all_io_objects.length; i++){//set all pins as outputs
  		(function (pinIndex){//need to create a scope for the current pin variable, because it is asynchronous
  			debug("    pin passed is " + this + "; pin index passed is " + pinIndex);//"this" is the first parameter passed -> the current pin
  			b.pinMode(this, all_io[all_io_objects[pinIndex]].cfg, function(err, pin){//configure and callback function
  				if(err)//if by the end of executing pinMode function, there is an error
  					console.error(err.message);//then the error is printed
  				else{//initial state, everyone LOW because HIGH state means ON
  					if(all_io[all_io_objects[pinIndex]].cfg == b.OUTPUT){//if pin is configured as digital output
  						debug('    pin ' + pin + ' ready[OUTPUT], ' + (ioStatus.cfgok+1) + "/" + ioStatus.total + "pins configured");
  						b.digitalWriteSync(pin, all_io[all_io_objects[pinIndex]].state);//state is LOW because of initial values
  						//ioStatus.cfgok++;
  						ioStatus.newGpio();//indicates one more pin is configured as gpio
  						if(ioStatus.cfgok == ioStatus.total){//if all pins are already configured
  							//interval = setInterval(function(){ioTest()}, 5000);//then start the blinking test very slow
  							debug(ioStatus.gpio + " pins as GPIO, " + ioStatus.pwm + " as PWM, " + 
  								ioStatus.analog + " as ANALOG, " + ioStatus.interrupt + " as INTERRUPT");
  						}
  					}
  					else if(all_io[all_io_objects[pinIndex]].cfg == b.ANALOG_OUTPUT){//if pin is configured as PWM
  						debug('    pin ' + pin + ' ready[PWM], ' + (ioStatus.cfgok+1) + "/" + ioStatus.total + "pins configured");
  						b.analogWrite(servo_pwm.id,servo_pwm.state.duty,servo_pwm.state.freq, function(err_wr){//try to configure
  							if(err_wr){//if error
  								debug(err_wr);
  							}
  							else{//if ok
  								ioStatus.newPwm();//indicates one more pin is configured as PWM
  								if(ioStatus.cfgok == ioStatus.total){//if all pins are already configured
  									//interval = setInterval(function(){ioTest()}, 5000);//then start the blinking test very slow
  									debug(ioStatus.gpio + " pins as GPIO, " + ioStatus.pwm + " as PWM, " + 
  										ioStatus.analog + " as ANALOG, " + ioStatus.interrupt + " as INTERRUPT");
  								}
  							}
  						});
  					}
  				}
  					
  			});//everyone is output
  		//get all the object keys as vector and use it to access all the object keys
  		}).call(all_io[all_io_objects[i]].id,i);//passes pin as "this" and index as pinIndex, only works properly in strict mode
  	}
  };
  
  module.exports.ioTest = function (){
  	/*This function do some blinking thing, it should be called inside setInterval(),like:
  	setInterval(ioTest, interval);//period = interval*IOpins = 500ms*9 = 4.5s*/
  	var on_count = 0;//number of io turned b.HIGH
  	var last_on; //number of last io b.HIGH
  	
  	for(var i = 0; i < all_io_objects.length; i++){//check all
  		if(all_io[all_io_objects[i]].state == b.HIGH){//if HIGH
  			on_count++;//one more io HIGH
  			last_on = i;//this is the last io HIGH
  		}
  	}
  	if(on_count == 1){//if only one IO HIGH
  		if(last_on == 8){//if last pin is the one HIGH
  			//debug('Activating pin 0');
  			all_io[all_io_objects[last_on]].state = b.LOW;//turn it LOW
  			all_io[all_io_objects[0]].state = b.HIGH;//and next one HIGH, which means the first
  			b.digitalWriteSync(all_io[all_io_objects[last_on]].id, all_io[all_io_objects[last_on]].state);
  			b.digitalWriteSync(all_io[all_io_objects[0]].id, all_io[all_io_objects[0]].state);
  		}
  		else{//if any pin but the last is the one HIGH
  			//debug('Activating pin ' + (last_on+1));
  			all_io[all_io_objects[last_on]].state = b.LOW;//turn it LOW
  			all_io[all_io_objects[last_on+1]].state = b.HIGH;//and next one HIGH
  			b.digitalWriteSync(all_io[all_io_objects[last_on]].id, all_io[all_io_objects[last_on]].state);
  			b.digitalWriteSync(all_io[all_io_objects[last_on+1]].id, all_io[all_io_objects[last_on+1]].state);
  			}
  	}
  	else{//if there is more than one IO HIGH
  		for(i = 1; i < all_io_objects.length; i++){
  			all_io[all_io_objects[i]].state = b.LOW;//turn all but first LOW
  			b.digitalWriteSync(all_io[all_io_objects[i]].id, all_io[all_io_objects[i]].state);
  		}
  		all_io[all_io_objects[0]].state = b.HIGH;//turn first HIGH
  		b.digitalWriteSync(all_io[all_io_objects[0]].id, all_io[all_io_objects[0]].state);
  	}
  };
  
  function collect() {//function concat objects
  	var ret = {};//the new object
  	var len = arguments.length;//the total number of objects passed to collect
  	for (var i=0; i<len; i++) {//do it for every object passed
  		for (var p in arguments[i]) {//iterate the i-eth object passed
  			if (arguments[i].hasOwnProperty(p)) {//whenever there is a property
  				ret[p] = arguments[i][p];//add the property to the new object
  			}
  		}
  	}
  	return ret;
  }