#include "LoRaRadio.h"

boolean _transmitted = false;

lmic_pinmap lmic_pins = {0};
void (*LoRaRadio::downlinkHandler)(u1_t, u1_t, u1_t*) = NULL;
void (*LoRaRadio::sendCompleteHandler)(void) = NULL;

LoRaRadio::LoRaRadio(PinMap pinMap, dr_t dataRate, s1_t txPower) :_pinMap(pinMap), _dataRate(dataRate), _txPower(txPower)
{
  lmic_pins.nss = pinMap._nss;
  lmic_pins.rxtx = pinMap._rxtx;
  lmic_pins.rst = pinMap._rst;
  lmic_pins.dio[0] = pinMap._dio[0];
  lmic_pins.dio[1] = pinMap._dio[1];
  lmic_pins.dio[2] = pinMap._dio[2];
}

void LoRaRadio::init()
{
  os_init();
  LMIC_reset();
  LMIC_setDrTxpow(_dataRate, _txPower);
}

void LoRaRadio::setMCUClockError(u2_t percent)
{
  LMIC_setClockError(MAX_CLOCK_ERROR * percent / 100);
}

void LoRaRadio::setTTNSession(u4_t channelId, devaddr_t deviceAddress, xref2u1_t networkSystemKey, xref2u1_t applicationSystemKey, bit_t linkCheckMode)
{
  LMIC_setSession(channelId, deviceAddress, networkSystemKey, applicationSystemKey);
  LMIC_setLinkCheckMode(linkCheckMode);
}

void LoRaRadio::setRadioEUChannels()
{
    LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
    LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band
    LMIC.dn2Dr = DR_SF9;
}

void LoRaRadio::send(u1_t port, uint8_t *data, uint8_t length, u1_t confirmed)
{ 
  if (LMIC.opmode & OP_TXRXPEND) 
  {
    //Serial.println(F("OP_TXRXPEND, not sending"));
  }
  else
  {
     // Prepare upstream data transmission at the next possible time.
     LMIC_setTxData2(port, data, length, confirmed);
     Serial.println("Packet queued");
   }
}

void LoRaRadio::run()
{
  os_runloop_once();
}

void LoRaRadio::setDownlinkHandler(void (*funcP)(u1_t, u1_t, u1_t*))
{
  downlinkHandler = funcP;
}

void LoRaRadio::setSendCompleteHandler(void (*funcP)(void))
{
  sendCompleteHandler = funcP;
}

/*
 * Here, we declare the onEvent function required by the LMIC
 */
void onEvent(ev_t ev)
{
  switch(ev)
  {
    case EV_TXCOMPLETE:
      //Event telling us that the data was transmitted
	  if(LoRaRadio::sendCompleteHandler != NULL)
          (*LoRaRadio::sendCompleteHandler)();
	  
      //It is also here that we check for downlinks
      if(LMIC.dataLen)
      {
        //Data is available
        if(LoRaRadio::downlinkHandler != NULL)
          (*LoRaRadio::downlinkHandler)(LMIC.dataLen, LMIC.dataBeg, LMIC.frame);
      }
      break;
    case EV_RXCOMPLETE:
      // data received in ping slot
      break;
  }
}

void LoRaRadio::disableEUChannel(u1_t channel)
{
  LMIC_disableChannel(channel);
}

void LoRaRadio::disableAllEUChannelsBut(u1_t channel)
{
  for(int i(0); i < 9; i++)
    if(i != channel)
      LMIC_disableChannel(i);
}
