text: /* CONFIGURATION */
  
  var OpenVidu = require('openvidu-node-client').OpenVidu;
  var OpenViduRole = require('openvidu-node-client').OpenViduRole;
  var RecordingMode = require('openvidu-node-client').RecordingMode;
  var Recording = require('openvidu-node-client').Recording;
  
  // Check launch arguments: must receive openvidu-server URL and the secret
  if (process.argv.length != 4) {
      console.log("Usage: node " + __filename + " OPENVIDU_URL OPENVIDU_SECRET");
      process.exit(-1);
  }
  // For demo purposes we ignore self-signed certificate
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
  
  // Node imports
  var express = require('express');
  var fs = require('fs');
  var session = require('express-session');
  var https = require('https');
  var bodyParser = require('body-parser'); // Pull information from HTML POST (express4)
  var app = express(); // Create our app with express
  
  // Server configuration
  app.use(session({
      saveUninitialized: true,
      resave: false,
      secret: 'MY_SECRET'
  }));
  app.use(express.static(__dirname + '/public')); // Set the static files location
  app.use(bodyParser.urlencoded({
      'extended': 'true'
  })); // Parse application/x-www-form-urlencoded
  app.use(bodyParser.json()); // Parse application/json
  app.use(bodyParser.json({
      type: 'application/vnd.api+json'
  })); // Parse application/vnd.api+json as json
  
  // Listen (start app with node server.js)
  var options = {
      key: fs.readFileSync('openvidukey.pem'),
      cert: fs.readFileSync('openviducert.pem')
  };
  https.createServer(options, app).listen(5000);
  // Mock database
  var users = [{
      user: "publisher1",
      pass: "pass",
      role: OpenViduRole.PUBLISHER
  }, {
      user: "publisher2",
      pass: "pass",
      role: OpenViduRole.PUBLISHER
  }, {
      user: "subscriber",
      pass: "pass",
      role: OpenViduRole.SUBSCRIBER
  }];
  
  // Environment variable: URL where our OpenVidu server is listening
  var OPENVIDU_URL = process.argv[2];
  // Environment variable: secret shared with our OpenVidu server
  var OPENVIDU_SECRET = process.argv[3];
  
  console.log(OPENVIDU_SECRET, OPENVIDU_URL);
  // Entrypoint to OpenVidu Node Client SDK
  var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
  
  // Collection to pair session names with OpenVidu Session objects
  var mapSessions = {};
  // Collection to pair session names with tokens
  var mapSessionNamesTokens = {};
  // Collection to pair session IDs with names
  var mapSessionIDs = new Map();
  
  console.log("App listening on port 5000");
  
  /* CONFIGURATION */
  
  
  
  /* REST API */
  
  // Login
  app.post('/api-login/login', function (req, res) {
  
      // Retrieve params from POST body
      var user = req.body.user;
      var pass = req.body.pass;
      console.log("Logging in | {user, pass}={" + user + ", " + pass + "}");
  
      if (login(user, pass)) { // Correct user-pass
          // Validate session and return OK 
          // Value stored in req.session allows us to identify the user in future requests
          console.log("'" + user + "' has logged in");
          req.session.loggedUser = user;
          res.status(200).send();
      } else { // Wrong user-pass
          // Invalidate session and return error
          console.log("'" + user + "' invalid credentials");
          req.session.destroy();
          res.status(401).send('User/Pass incorrect');
      }
  });
  
  // Logout
  app.post('/api-login/logout', function (req, res) {
      console.log("'" + req.session.loggedUser + "' has logged out");
      req.session.destroy();
      res.status(200).send();
  });
  
  // Get token (add new user to session)
  app.post('/api-sessions/get-token', function (req, res) {
      if (!isLogged(req.session)) {
          req.session.destroy();
          res.status(401).send('User not logged');
      } else {
          // The video-call to connect
          var sessionName = req.body.sessionName;
  
          // Role associated to this user
          var role = users.find(u => (u.user === req.session.loggedUser)).role;
  
          // Optional data to be passed to other users when this user connects to the video-call
          // In this case, a JSON with the value we stored in the req.session object on login
          var serverData = JSON.stringify({ serverData: req.session.loggedUser });
  
          console.log("Getting a token | {sessionName}={" + sessionName + "}");
  
          // Build tokenOptions object with the serverData and the role
          var tokenOptions = {
              data: serverData,
              role: role
          };
  
          if (mapSessions[sessionName]) {
              // Session already exists
              console.log('Existing session ' + sessionName);
  
              // Get the existing Session from the collection
              var mySession = mapSessions[sessionName];
  
              // Generate a new token asynchronously with the recently created tokenOptions
              mySession.generateToken(tokenOptions)
                  .then(token => {
  
                      // Store the new token in the collection of tokens
                      mapSessionNamesTokens[sessionName].push(token);
  
                      // Return the token to the client
                      res.status(200).send({
                          0: token
                      });
                  })
                  .catch(error => {
                      console.error(error);
                  });
          } else {
              // New session
              console.log('New session ' + sessionName);
  
              var properties = {
                  recordingMode: RecordingMode.MANUAL,
                  defaultOutputMode: Recording.OutputMode.COMPOSED
              }
              // Create a new OpenVidu Session asynchronously
              OV.createSession(properties)
                  .then(session => {
                      // Store the new Session in the collection of Sessions
                      mapSessions[sessionName] = session;
                      // Store a new empty array in the collection of tokens
                      mapSessionNamesTokens[sessionName] = [];
                      // Store the new SessionID in the collection of Sessions
                      mapSessionIDs[session.sessionId] = session;
                      // Generate a new token asynchronously with the recently created tokenOptions
                      session.generateToken(tokenOptions)
                          .then(token => {
  
                              // Store the new token in the collection of tokens
                              mapSessionNamesTokens[sessionName].push(token);
  
                              // Return the Token to the client
                              res.status(200).send({
                                  0: token
                              });
                          })
                          // .catch(error => {
                          //     console.error("ERROR #1: ", error);
                          // });
                  })
                  // .catch(error => {
                  //     console.error("ERROR #2: ", error);
                  // });
          }
      }
  });
  
  // Remove user from session
  app.post('/api-sessions/remove-user', function (req, res) {
      if (!isLogged(req.session)) {
          req.session.destroy();
          res.status(401).send('User not logged');
      } else {
          // Retrieve params from POST body
          var sessionName = req.body.sessionName;
          var token = req.body.token;
          console.log('Removing user | {sessionName, token}={' + sessionName + ', ' + token + '}');
  
          // If the session exists
          if (mapSessions[sessionName] && mapSessionNamesTokens[sessionName]) {
              var tokens = mapSessionNamesTokens[sessionName];
              var index = tokens.indexOf(token);
  
              // If the token exists
              if (index !== -1) {
                  // Token removed
                  tokens.splice(index, 1);
                  console.log(sessionName + ': ' + tokens.toString());
              } else {
                  var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
                  console.log(msg);
                  res.status(500).send(msg);
              }
              if (tokens.length == 0) {
                  // Last user left: session must be removed
                  console.log(sessionName + ' empty!');
                  delete mapSessions[sessionName];
              }
              res.status(200).send();
          } else {
              var msg = 'Problems in the app server: the SESSION does not exist';
              console.log(msg);
              res.status(500).send(msg);
          }
      }
  });
  
  
  /* REST API */
  app.get('/api/sessions/:sessionId', function (req, res) {
      if (!isLogged(req.session)) {
          req.session.destroy();
          res.status(401).send('User not logged');
      } 
      else {
          var sessionId = req['params']['sessionId'];
          var relSession = mapSessionIDs[sessionId];
          relSession.fetch()
          .then(anyChange => {
              var activeConns = relSession.activeConnections;
              res.status(200).send(activeConns);
          })
      }
  });
  
  
  /* AUXILIARY METHODS */
  
  function login(user, pass) {
      return true; //(users.find(u => (u.user === user) && (u.pass === pass)));
  }
  
  function isLogged(session) {
      return (session.loggedUser != null);
  }
  
  function getBasicAuth() {
      return 'Basic ' + (new Buffer('OPENVIDUAPP:' + OPENVIDU_SECRET).toString('base64'));
  }
  
  /* AUXILIARY METHODS */
  