<!DOCTYPE html>
<!--
  This page was created to help debug and study webrtc issues such as
  bandwidth estimation problems. It allows one to easily launch a test
  case that establishs a connection between 2 peer connections
-->
<html>
<head>
<title>Loopback test</title>

<!-- In order to plot graphs, this tools uses google visualization API which is
     loaded via goog.load provided by google api. -->
<script src="//www.google.com/jsapi"></script>

<!-- This file is included to allow loopback_test.js instantiate a
     RTCPeerConnection on a browser and version agnostic way. -->
<script src="adapter.js"></script>

<!-- Provides class StatTracker used by loopback_test.js to keep track of
     RTCPeerConnection stats -->
<script src="stat_tracker.js"></script>

<!-- Provides LoopbackTest class which has the core logic for the test itself.
     Such as: create 2 peer connections, establish a call, filter turn
     candidates, constraint video bitrate etc.
  -->
<script src="loopback_test.js"></script>

<style>
#chart {
  height: 400px;
}

#control-range {
  height: 100px;
}
</style>
</head>
<body>
<div id="test-launcher">
  <p>Duration (s): <input id="duration" type="text"></p>
  <p>Max video bitrate (kbps): <input id="max-video-bitrate" type="text"></p>
  <p>Peer connection constraints: <input id="pc-constraints" type="text"></p>
  <p>Force TURN: <input id="force-turn" type="checkbox" checked></p>
  <p><input id="launcher-button" type="button" value="Run test">
  <div id="test-status" style="display:none"></div>
  <div id="dashboard">
    <div id="control-category"></div>
    <div id="chart"></div>
    <div id="control-range"></div>
  </div>
</div>
<script>
google.load('visualization', '1.0', {'packages':['controls']});

var durationInput = document.getElementById('duration');
var maxVideoBitrateInput = document.getElementById('max-video-bitrate');
var forceTurnInput = document.getElementById('force-turn');
var launcherButton = document.getElementById('launcher-button');
var autoModeInput = document.createElement('input');
var testStatus = document.getElementById('test-status');
var pcConstraintsInput = document.getElementById('pc-constraints');

launcherButton.onclick = start;

// Load parameters from the url if present. This allows one to link to
// a specific test configuration and is used to automatically pass parameters
// for scripts such as record-test.sh
function getURLParameter(name, default_value) {
  var search =
      RegExp('(^\\?|&)' + name + '=' + '(.+?)(&|$)').exec(location.search);
  if (search)
    return decodeURI(search[2]);
  else
    return default_value;
}

durationInput.value = getURLParameter('duration', 10);
maxVideoBitrateInput.value = getURLParameter('max-video-bitrate', 2000);
forceTurnInput.checked = (getURLParameter('force-turn', 'true') === 'true');
autoModeInput.checked = (getURLParameter('auto-mode', 'false') === 'true');
pcConstraintsInput.value = getURLParameter('pc-constraints', '');

if (autoModeInput.checked) start();

function start() {
  var durationMs = parseInt(durationInput.value) * 1000;
  var maxVideoBitrateKbps = parseInt(maxVideoBitrateInput.value);
  var forceTurn = forceTurnInput.checked;
  var autoClose = autoModeInput.checked;
  var pcConstraints = pcConstraintsInput.value == "" ?
                      null : JSON.parse(pcConstraintsInput.value);

  var updateStatusInterval;
  var testFinished = false;
  function updateStatus() {
    if (testFinished) {
      testStatus.innerHTML = 'Test finished';
      if (updateStatusInterval) {
	clearInterval(updateStatusInterval);
        updateStatusInterval = null;
      }
    } else {
      if (!updateStatusInterval) {
        updateStatusInterval = setInterval(updateStatus, 1000);
        testStatus.innerHTML = 'Running';
      }
      testStatus.innerHTML += '.';
    }
  }

  if (!(isFinite(maxVideoBitrateKbps) && maxVideoBitrateKbps > 0)) {
    // TODO(andresp): Get a better way to show errors than alert.
    alert("Invalid max video bitrate");
    return;
  }

  if (!(isFinite(durationMs) && durationMs > 0)) {
    alert("Invalid duration");
    return;
  }

  durationInput.disabled = true;
  forceTurnInput.disabled = true;
  maxVideoBitrateInput.disabled = true;
  launcherButton.style.display = 'none';
  testStatus.style.display = 'block';

  getUserMedia({audio:true, video:true},
                gotStream, function() {});

  function gotStream(stream) {
    updateStatus();
    var test = new LoopbackTest(stream, durationMs,
                                forceTurn,
                                pcConstraints,
                                maxVideoBitrateKbps);
    test.run(onTestFinished.bind(test));
  }

  function onTestFinished() {
    testFinished = true;
    updateStatus();
    if (autoClose) {
      window.close();
    } else {
      plotStats(this.getResults());
    }
  }
}

function plotStats(data) {
  var dashboard = new google.visualization.Dashboard(
      document.getElementById('dashboard'));

  var chart = new google.visualization.ChartWrapper({
      'containerId': 'chart',
      'chartType': 'LineChart',
      'options': { 'pointSize': 0, 'lineWidth': 1, 'interpolateNulls': true },
    });

  var rangeFilter = new google.visualization.ControlWrapper({
     'controlType': 'ChartRangeFilter',
     'containerId': 'control-range',
     'options': {
       'filterColumnIndex': 0,
       'ui': {
         'chartType': 'ScatterChart',
         'chartOptions': {
           'hAxis': {'baselineColor': 'none'}
         },
         'chartView': {
           'columns': [0, 1]
         },
         'minRangeSize': 1000 // 1 second
       }
     },
   });

  // Create a table with the columns of the dataset.
  var columnsTable = new google.visualization.DataTable();
  columnsTable.addColumn('number', 'columnIndex');
  columnsTable.addColumn('string', 'columnLabel');
  var initState = {selectedValues: []};
  for (var i = 1; i < data.getNumberOfColumns(); i++) {
    columnsTable.addRow([i, data.getColumnLabel(i)]);
    initState.selectedValues.push(data.getColumnLabel(i));
  }

  var columnFilter = new google.visualization.ControlWrapper({
    controlType: 'CategoryFilter',
    containerId: 'control-category',
    dataTable: columnsTable,
    options: {
      filterColumnLabel: 'columnLabel',
      ui: {
        label: '',
        allowNone: false,
        selectedValuesLayout: 'aside'
      }
    },
    state: initState
  });
  google.visualization.events.addListener(columnFilter, 'statechange',
    function () {
      var state = columnFilter.getState();
      var row;
      var columnIndices = [0];
      for (var i = 0; i < state.selectedValues.length; i++) {
        row = columnsTable.getFilteredRows([{
            column: 1,
            value: state.selectedValues[i]}])[0];
        columnIndices.push(columnsTable.getValue(row, 0));
      }
      // Sort the indices into their original order
      columnIndices.sort(function (a, b) { return (a - b); });
      chart.setView({columns: columnIndices});
      chart.draw();
    });

  columnFilter.draw();
  dashboard.bind([rangeFilter], [chart]);
  dashboard.draw(data);
}
</script>
</body>
</html>
