// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// botmanager.js module allows a test to spawn bots that expose an RPC API
// to be controlled by tests.
var http = require('http');
var child = require('child_process');
var Browserify = require('browserify');
var Dnode = require('dnode');
var Express = require('express');
var WebSocketServer = require('ws').Server;
var WebSocketStream = require('websocket-stream');

// BotManager runs a HttpServer that serves bots assets and and WebSocketServer
// that listens to incoming connections. Once a connection is available it
// connects it to bots pending endpoints.
//
// TODO(andresp): There should be a way to control which bot was spawned
// and what bot instance it gets connected to.
BotManager = function () {
  this.webSocketServer_ = null;
  this.bots_ = [];
  this.pendingConnections_ = [];
  this.androidDeviceManager_ = new AndroidDeviceManager();
}

BotManager.BotTypes = {
  CHROME : 'chrome',
  ANDROID_CHROME : 'android-chrome',
};

BotManager.prototype = {
  createBot_: function (name, botType, callback) {
    switch(botType) {
      case BotManager.BotTypes.CHROME:
        return new BrowserBot(name, callback);
      case BotManager.BotTypes.ANDROID_CHROME:
        return new AndroidChromeBot(name, this.androidDeviceManager_,
            callback);
      default:
        console.log('Error: Type ' + botType + ' not supported by rtc-Bot!');
        process.exit(1);
    }
  },

  spawnNewBot: function (name, botType, callback) {
    this.startWebSocketServer_();
    var bot = this.createBot_(name, botType, callback);
    this.bots_.push(bot);
    this.pendingConnections_.push(bot.onBotConnected.bind(bot));
  },

  startWebSocketServer_: function () {
    if (this.webSocketServer_) return;

    this.app_ = new Express();

    this.app_.use('/bot/api.js',
        this.serveBrowserifyFile_.bind(this,
          __dirname + '/bot/api.js'));

    this.app_.use('/bot/', Express.static(__dirname + '/bot'));

    this.server_ = http.createServer(this.app_);

    this.webSocketServer_ = new WebSocketServer({ server: this.server_ });
    this.webSocketServer_.on('connection', this.onConnection_.bind(this));

    this.server_.listen(8080);
  },

  onConnection_: function (ws) {
    var callback = this.pendingConnections_.shift();
    callback(new WebSocketStream(ws));
  },

  serveBrowserifyFile_: function (file, request, result) {
    // TODO(andresp): Cache browserify result for future serves.
    var browserify = new Browserify();
    browserify.add(file);
    browserify.bundle().pipe(result);
  }
}

// A basic bot waits for onBotConnected to be called with a stream to the actual
// endpoint with the bot. Once that stream is available it establishes a dnode
// connection and calls the callback with the other endpoint interface so the
// test can interact with it.
Bot = function (name, callback) {
  this.name_ = name;
  this.onbotready_ = callback;
}

Bot.prototype = {
  log: function (msg) {
    console.log("bot:" + this.name_ + " > " + msg);
  },

  name: function () { return this.name_; },

  onBotConnected: function (stream) {
    this.log('Connected');
    this.stream_ = stream;
    this.dnode_ = new Dnode();
    this.dnode_.on('remote', this.onRemoteFromDnode_.bind(this));
    this.dnode_.pipe(this.stream_).pipe(this.dnode_);
  },

  onRemoteFromDnode_: function (remote) {
    this.onbotready_(remote);
  }
}

// BrowserBot spawns a process to open "http://localhost:8080/bot/".
//
// That page once loaded, connects to the websocket server run by BotManager
// and exposes the bot api.
BrowserBot = function (name, callback) {
  Bot.call(this, name, callback);
  this.spawnBotProcess_();
}

BrowserBot.prototype = {
  spawnBotProcess_: function () {
    this.log('Spawning browser');
    child.exec('google-chrome "http://localhost:8080/bot/"');
  },

  __proto__: Bot.prototype
}

// AndroidChromeBot spawns a process to open
// "http://localhost:8080/bot/browser/" on chrome for Android.
AndroidChromeBot = function (name, androidDeviceManager, callback) {
  Bot.call(this, name, callback);
  androidDeviceManager.getNewDevice(function (serialNumber) {
    this.serialNumber_ = serialNumber;
    this.spawnBotProcess_();
  }.bind(this));
}

AndroidChromeBot.prototype = {
  spawnBotProcess_: function () {
    this.log('Spawning Android device with serial ' + this.serialNumber_);
    var runChrome = 'adb -s ' + this.serialNumber_ + ' shell am start ' +
    '-n com.android.chrome/com.google.android.apps.chrome.Main ' +
    '-d http://localhost:8080/bot/';
    child.exec(runChrome, function (error, stdout, stderr) {
      if (error) {
        this.log(error);
        process.exit(1);
      }
      this.log('Opening Chrome for Android...');
      this.log(stdout);
    }.bind(this));
  },

  __proto__: Bot.prototype
}

AndroidDeviceManager = function () {
  this.connectedDevices_ = [];
}

AndroidDeviceManager.prototype = {
  getNewDevice: function (callback) {
    this.listDevices_(function (devices) {
      for (var i = 0; i < devices.length; i++) {
        if (!this.connectedDevices_[devices[i]]) {
          this.connectedDevices_[devices[i]] = devices[i];
          callback(this.connectedDevices_[devices[i]]);
          return;
        }
      }
      if (devices.length == 0) {
        console.log('Error: No connected devices!');
      } else {
        console.log('Error: There is no enough connected devices.');
      }
      process.exit(1);
    }.bind(this));
  },

  listDevices_: function (callback) {
    child.exec('adb devices' , function (error, stdout, stderr) {
      var devices = [];
      if (error || stderr) {
        console.log(error || stderr);
      }
      if (stdout) {
        // The first line is "List of devices attached"
        // and the following lines:
        // <serial number>  <device/emulator>
        var tempList = stdout.split("\n").slice(1);
        for (var i = 0; i < tempList.length; i++) {
          if (tempList[i] == "") {
            continue;
          }
          devices.push(tempList[i].split("\t")[0]);
        }
      }
      callback(devices);
    });
  },
}
module.exports = BotManager;
