/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

var randomBytes = require('crypto').randomBytes;
var request = require('request');
var conf = require('./config').conf;

// Be sure to use the exported OpenTok so we can mock it in the
// tests.
exports.OpenTok = require('opentok');

function TokBox(settings) {
  this.credentials = settings.credentials;
  if (settings.retryOnError === undefined) {
    settings.retryOnError = 3;
  }
  this.retryOnError = settings.retryOnError;
  this.tokenDuration = settings.tokenDuration;
  this._opentok = {};
  for (var channel in this.credentials) {
    this._opentok[channel] = new exports.OpenTok(
      this.credentials[channel].apiKey,
      this.credentials[channel].apiSecret, {
        apiUrl: this.credentials[channel].apiUrl || conf.get("tokBox").apiUrl,
        timeout: settings.timeout
      }
    );
  }
}

TokBox.prototype = {
  getSessionTokens: function(options, cb) {
    if (cb === undefined) {
      cb = options;
      options = undefined;
    }

    options = options || {};

    if (options.retry === undefined) {
      options.retry = this.retryOnError;
    }

    var opentok;

    if (this.credentials.hasOwnProperty(options.channel)) {
      opentok = this._opentok[options.channel];
    } else {
      opentok = this._opentok["default"];
    }

    var self = this;
    opentok.createSession({
      mediaMode: 'relayed'
    }, function(err, session) {
        if (err !== null) {
          options.retry--;
          if (options.retry <= 0) {
            cb(err);
            return;
          }
          self.getSessionTokens(options, cb);
          return;
        }
        var sessionId = session.sessionId;
        var now = Math.round(Date.now() / 1000.0);
        var expirationTime = now + self.tokenDuration;
        cb(null, {
          apiKey: opentok.apiKey,
          sessionId: sessionId,
          callerToken: opentok.generateToken(sessionId, {
            role: 'publisher',
            expireTime: expirationTime
          }),
          calleeToken: opentok.generateToken(sessionId, {
            role: 'publisher',
            expireTime: expirationTime
          })
        });
      }
    );
  },
  ping: function(options, cb) {
    if (cb === undefined) {
      cb = options;
      options = undefined;
    }

    options = options || {};
    var timeout = options.timeout;

    var opentok = new exports.OpenTok(
      this.credentials.default.apiKey,
      this.credentials.default.apiSecret, {
        apiUrl: this.credentials.default.apiUrl || conf.get("tokBox").apiUrl,
        timeout: timeout
      }
    );

    opentok.createSession({
      mediaMode: 'relayed'
    }, function(err) {
      if (err !== null) {
        cb(err);
        return;
      }
      cb(null);
    });
  }
};

function FakeTokBox() {
  this._counter = 0;
  this.serverURL = conf.get("fakeTokBoxURL");
  this.apiKey = "falseApiKey";
}

FakeTokBox.prototype = {
  _urlSafeBase64RandomBytes: function(number_of_bytes) {
    return randomBytes(number_of_bytes).toString('base64')
                 .replace(/\+/g, '-').replace(/\//g, '_');
  },

  _fakeApiKey: function() {
    return "4468744";
  },

  _fakeSessionId: function() {
    this._token = 0;
    this._counter += 1;
    return this._counter + '_' + this._urlSafeBase64RandomBytes(51);

  },

  _generateFakeToken: function() {
    this._token += 1;
    return 'T' + this._token + '==' + this._urlSafeBase64RandomBytes(293);
  },

  getSessionTokens: function(options, cb) {
    if (cb === undefined) {
      cb = options;
      options = {};
    }
    var self = this;
    // Do a real HTTP call to have a realistic behavior.
    request.get({
      url: self.serverURL,
      timeout: options.timeout
    }, function(err) {
      cb(err, {
        apiKey: self._fakeApiKey(),
        sessionId: self._fakeSessionId(),
        callerToken: self._generateFakeToken(),
        calleeToken: self._generateFakeToken()
      });
    });
  },
  ping: function(options, cb) {
    this.getSessionTokens(options, cb);
  }
};


exports.TokBox = TokBox;
exports.FakeTokBox = FakeTokBox;
exports.OpenTok = exports.OpenTok;
exports.request = request;

@@ -1046,16 +1046,17 @@
 ype = %7B%0A
+%0A
   getSes
@@ -1051,38 +1051,32 @@
  %7B%0A%0A  getSession
-Tokens
 : function(optio
@@ -1796,24 +1796,189 @@
         %7D%0A  
+      cb(session, opentok);%0A    %7D);%0A  %7D,%0A%0A  getSessionTokens: function(options, cb) %7B%0A    var self = this;%0A    this.getSession(options, function(session, opentok) %7B%0A
       var se
@@ -2006,18 +2006,16 @@
 sionId;%0A
-  
       va
@@ -2055,18 +2055,16 @@
 000.0);%0A
-  
       va
@@ -2110,26 +2110,24 @@
 tion;%0A      
-  
 cb(null, %7B%0A 
@@ -2121,26 +2121,24 @@
  cb(null, %7B%0A
-  
         apiK
@@ -2153,26 +2153,24 @@
 tok.apiKey,%0A
-  
         sess
@@ -2191,26 +2191,24 @@
 Id,%0A        
-  
 callerToken:
@@ -2235,34 +2235,32 @@
 en(sessionId, %7B%0A
-  
           role: 
@@ -2274,34 +2274,32 @@
 her',%0A          
-  
 expireTime: expi
@@ -2321,16 +2321,12 @@
     
- 
- 
 %7D),%0A
-  
     
@@ -2379,34 +2379,32 @@
 Id, %7B%0A          
-  
 role: 'publisher
@@ -2408,34 +2408,32 @@
 her',%0A          
- 
- 
 expireTime: expi
@@ -2455,15 +2455,11 @@
     
-  
 %7D)%0A
-  
     
@@ -2464,28 +2464,21 @@
     %7D);%0A
-  
     %7D
-%0A    
 );%0A  %7D,%0A

Update tokbox code to return the session only