function Pinger (options) {
    this.options = {
        pingUrl: "/mainib/web.p",
        pingData: {},
        cbError: function (data){},
        cbSuccess: function (data){},
        pingInitialInterval: 2000, /*ms*/
        pingTimeout: 60000, /*ms*/
        pingFactor: 1.5,
        pingDelay: 0,
        autoStart: false,
        counterDisplay: $("#waittim"),
        msgTexts : {
            timeout: "timeout",
            invalidResponse: "invalid response",
            invalidStatus: "invalid status",
            serverError: "server error"
        }
    };
    this.timerHolder = null;
    this.pingStart = null;
    this.setup(options); /*override options*/
    
    
    if (this.options.autoStart === true){
        this.pingStart = new Date().getTime();
        this.startTimer();
        
        if (this.options.pingDelay > 0){
            var that = this;
            setTimeout(function(){that.doPing()}, that.options.pingDelay);
        } else {
            this.doPing();
        }
    }
}

Pinger.prototype.setup = function(options) {
    if (typeof options !== "object") return;
    for(var opt in this.options){
        if (typeof options[opt] === typeof this.options[opt]) this.options[opt] = options[opt];
    }
    /*set initial values*/
    this.currentPingInterval = this.options.pingInitialInterval;
    this.lastPingInterval = this.options.pingInitialInterval;
};

Pinger.prototype.startPinger = function() {
    this.pingStart = new Date().getTime();
    this.startTimer();
    this.doPing();
};

Pinger.prototype.doPing = function() {
    var that = this, options = that.options, status = null;
    $.ajax({
          url: that.options.pingUrl,
          type: 'GET',
          dataType: 'json',
          data: that.options.pingData,
          success: function success(data, textStatus, jqXhr){
        	  if(that.timerHolder === null) {
        		  return;
        	  }
              if (that.isTimeout() === true) {
                  that.stopTimer();
                  that.options.cbError({"text":that.options.msgTexts.timeout, "status": "timeout"});
                  return;
              }
              status = that.getStatus(data);
              switch (status){
                  case 'done':
                      that.stopTimer();
                      that.options.cbSuccess(data);
                    return;
                  break;
                  case 'wait':
                    setTimeout(function(){that.doPing()}, that.getPingInterval());
                    return;
                  break;
                  case 'wait_challenge':
                      setTimeout(function(){that.doPing()}, 1000);
                      return;
                    break;
                  default:
                      that.stopTimer();
                      that.options.cbError({"text":that.options.msgTexts.invalidStatus, "status": status});
                      return;
                  break;
              }
          },
          error: function error(jqXhr, textStatus, String){
              that.stopTimer();
              that.options.cbError({"text": that.options.msgTexts.serverError});
              return;
          }
    });
};

Pinger.prototype.getStatus = function(data) {
    if (typeof data === "undefined" || typeof data.sta === "undefined")
        return "undefined";
    return data.sta;
}

Pinger.prototype.isTimeout = function() {
    var now = new Date().getTime();
    return now - this.pingStart > this.options.pingTimeout;
}

Pinger.prototype.getPingInterval = function() {
    this.currentPingInterval = this.lastPingInterval * this.options.pingFactor;
    this.lastPingInterval = this.currentPingInterval;
    return this.currentPingInterval;
}

Pinger.prototype.getTimeLeft = function() {
    var now = new Date().getTime();
    var timeLeft = this.options.pingTimeout - (now - this.pingStart);
    if (timeLeft < 0) {timeLeft = 0;}
    return Math.round(timeLeft / 1000);
}

Pinger.prototype.startTimer = function() {
    var that = this;
    this.timerHolder = setInterval(function(){that.options.counterDisplay.text(that.getTimeLeft());}, 1000);
}

Pinger.prototype.stopTimer = function() {
    clearInterval(this.timerHolder);
    this.timerHolder = null;
}
