/*
 * Copyright (c) 2013-2015 node-coap contributors.
 *
 * node-coap is licensed under an MIT +no-false-attribs license.
 * All rights not explicitly granted in the MIT license are reserved.
 * See the included LICENSE file for more details.
 */

var parameters      = require('./parameters')
  , util            = require('util')
  , EventEmitter    = require('events').EventEmitter
  , parse           = require('coap-packet').parse

function RetrySend(sock, port, host) {
  if (!(this instanceof RetrySend))
    return new RetrySend(port, host)

  var that    = this

  this._sock  = sock

  this._port  = port || parameters.coapPort

  this._host  = host

  this._sendAttemp = 0
  this._lastMessageId = -1
  this._currentTime = parameters.ackTimeout * (1 + (parameters.ackRandomFactor - 1) * Math.random()) * 1000

  this._bOff  = function() {
    that._currentTime = that._currentTime * 2
    that._send()
  }
}

util.inherits(RetrySend, EventEmitter)

RetrySend.prototype._send = function(avoidBackoff) {
  var that = this

  this._sock.send(this._message, 0, this._message.length,
                  this._port, this._host, function(err, bytes) {
                    that.emit('sent', err, bytes)
                    if (err) {
                      that.emit('error', err)
                    }
                  })

  var messageId = parse(this._message).messageId
  if (messageId != this._lastMessageId) {
    this._lastMessageId = messageId
    this._sendAttemp = 0
  }

  if (!avoidBackoff && ++this._sendAttemp <= parameters.maxRetransmit)
    this._bOffTimer = setTimeout(this._bOff, this._currentTime)

  this.emit('sending', this._message)
}

RetrySend.prototype.send = function(message, avoidBackoff) {
  var that = this

  this._message = message
  this._send(avoidBackoff)

  if (!avoidBackoff)
    this._timer = setTimeout(function() {
      var err  = new Error('No reply in ' + parameters.exchangeLifetime + 's')
      err.retransmitTimeout = parameters.exchangeLifetime;
      that.emit('error', err)
      that.emit('timeout', err)
    }, parameters.exchangeLifetime * 1000)
}

RetrySend.prototype.reset = function() {
  clearTimeout(this._timer)
  clearTimeout(this._bOffTimer)
}

module.exports = RetrySend

@@ -1722,32 +1722,46 @@
  var that = this
+%0A    , timeout
 %0A%0A  this._messag
@@ -1798,29 +1798,34 @@
 Backoff)%0A%0A  
-if (!
+timeout = 
 avoidBackoff
@@ -1824,20 +1824,67 @@
 dBackoff
-)%0A  
+ ? parameters.maxRTT : parameters.exchangeLifetime%0A
   this._
@@ -1911,26 +1911,24 @@
 unction() %7B%0A
-  
     var err 
@@ -1961,43 +1961,23 @@
 ' + 
-parameters.exchangeLife
 time
+out
  + 's')%0A
     
@@ -1972,18 +1972,16 @@
  + 's')%0A
-  
     err.
@@ -2004,43 +2004,21 @@
 t = 
-parameters.exchangeLife
 time
+out
 ;%0A    
-  
 that
@@ -2033,26 +2033,24 @@
 rror', err)%0A
-  
     that.emi
@@ -2073,40 +2073,18 @@
 )%0A  
- 
- 
 %7D, 
-parameters.exchangeLife
 time
+out
  * 1

Fix for updated non-confirmable request tests