var mrf24j40 = require('node-mrf24j40');
var MRF24J40 = mrf24j40.MRF24J40;
var ControlRegister = mrf24j40.ControlRegister;
var FIFO = mrf24j40.FIFO;

var osnp = require('node-osnp');
var FrameType = osnp.FrameType;
var AddressingMode = osnp.AddressingMode;

var radio;
var frameQueue = [];
var cbCache = {};
var transmissionPending = false;

exports.start = function() {
  if (process.platform == 'linux') {
    radio = new MRF24J40('raspi');    
  }

  osnp.setPANID(new Buffer([0xfe, 0xca]));
  osnp.setShortAddress(new Buffer([0xbe, 0xba]));      
  
  if (radio) {
    radio.on('frame', handleReceived);
    radio.on('transmitted', handleTransmitted);
    radio.initialize(11);
    radio.setPANCoordinator();
    radio.setPANID(osnp.getPANID());
    radio.setShortAddress(osnp.getShortAddress());      
  }
}

exports.pair = function(device, pairingData, cb) {
  //TODO: here assign short address from eui
  cb(device);
}

exports.unpair = function(device, cb) {
  //TODO: remove association here
  cb(device);
}

exports.discoverDevices = function(cb) {
  //substitute with real code
  var discoveredDevices = [];
  
  if (radio) {
    discoveredDevices = [ new OSNPProtocolInfo(new Buffer([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), new Buffer([0xef, 0xbe]))];
  }

  for(var i = 0, len = discoveredDevices.length; i < len; i++) {
    var dev = discoveredDevices[i];
    cb(dev.toID(), dev);
  }
}

exports.send = function(device, data, cb) {  
  var frameControlLow = osnp.makeFrameControlLow(FrameType.DATA, false, false, true, true);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, 0x00, AddressingMode.SHORT_ADDRESS);
  
  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationAddress = device.protocolInfo.shortAddress;
  frame.payload = data;
  
  frameQueue.push(frame);
  cbCache[device.protocolInfo.shortAddress.toString('hex')] = cb;
  trySend();
}

function trySend() {
  if (!transmissionPending && (frameQueue.length > 0)) {
    var frame = frameQueue.shift();
    transmissionPending = frame;
    radio.transmit(frame.encode());
  }
}

function handleReceived(rawFrame, lqi, rssi) {
  var frame = osnp.parseFrame(rawFrame);
  var cb = cbCache[frame.sourceAddress.toString('hex')];
  
  //TODO: what to do with data generated by the device (notification)
  if (cb) {
    delete cbCache[frame.sourceAddress.toString('hex')];
    cb(frame.payload);
  }
}

function handleTransmitted(txErr, ccaErr) {
  if(ccaErr) {
    frameQueue.push(transmissionPending);
  } else if (txErr) {
    delete cbCache[transmissionPending.destinationAddress.toString('hex')];    
  }
  
  transmissionPending = null;
  trySend();
}

function OSNPProtocolInfo(eui, shortAddress) {
  this.eui = eui;
  this.shortAddress = shortAddress;
}

OSNPProtocolInfo.prototype.toID = function() {
  return this.eui.toString('hex');
}


@@ -208,16 +208,54 @@
 meType;%0A
+var FrameVersion = osnp.FrameVersion;%0A
 var Addr
@@ -1662,20 +1662,34 @@
 DDRESS, 
-0x
+FrameVersion.V2
 00
+3
 , Addres
@@ -2136,37 +2136,224 @@
     
-radio.transmit(frame.encode()
+var frameLength = frame.getEncodedLength();%0A    var buf = new Buffer(frameLength + 2);%0A    buf%5B0%5D = frameLength - frame.payload.length;%0A    buf%5B1%5D = frameLength;%0A    frame.encode(buf.slice(2));%0A    radio.transmit(buf
 );%0A 

send header length and frame length