<!doctype html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>RTCPeerConnection Connection Test</title>
  <script src="RTCPeerConnection-helper.js"></script>
</head>
<body>
  <div id="log"></div>
  <div>
    <video id="local-view" muted autoplay="autoplay"></video>
    <video id="remote-view" muted autoplay="autoplay"/>
    </video>
  </div>

  <!-- These files are in place when executing on W3C. -->
  <script src="/resources/testharness.js"></script>
  <script src="/resources/testharnessreport.js"></script>
  <script type="text/javascript">
  var test = async_test('Can set up a basic WebRTC call.');

  var gFirstConnection = null;
  var gSecondConnection = null;

  // if the remote video gets video data that implies the negotiation
  // as well as the ICE and DTLS connection are up.
  document.getElementById('remote-view')
      .addEventListener('loadedmetadata', function() {
    // Call negotiated: done.
    test.done();
  });

  function getNoiseStreamOkCallback(localStream) {
    gFirstConnection = new RTCPeerConnection(null);
    gFirstConnection.onicecandidate = onIceCandidateToFirst;
    localStream.getTracks().forEach(function(track) {
      gFirstConnection.addTrack(track, localStream);
    });
    gFirstConnection.createOffer().then(onOfferCreated, failed('createOffer'));

    var videoTag = document.getElementById('local-view');
    videoTag.srcObject = localStream;
  };

  var onOfferCreated = test.step_func(function(offer) {
    gFirstConnection.setLocalDescription(offer);

    // This would normally go across the application's signaling solution.
    // In our case, the "signaling" is to call this function.
    receiveCall(offer.sdp);
  });

  function receiveCall(offerSdp) {
    gSecondConnection = new RTCPeerConnection(null);
    gSecondConnection.onicecandidate = onIceCandidateToSecond;
    gSecondConnection.ontrack = onRemoteTrack;

    var parsedOffer = new RTCSessionDescription({ type: 'offer',
                                                  sdp: offerSdp });
    gSecondConnection.setRemoteDescription(parsedOffer);

    gSecondConnection.createAnswer().then(onAnswerCreated,
                                   failed('createAnswer'));
  };

  var onAnswerCreated = test.step_func(function(answer) {
    gSecondConnection.setLocalDescription(answer);

    // Similarly, this would go over the application's signaling solution.
    handleAnswer(answer.sdp);
  });

  function handleAnswer(answerSdp) {
    var parsedAnswer = new RTCSessionDescription({ type: 'answer',
                                                   sdp: answerSdp });
    gFirstConnection.setRemoteDescription(parsedAnswer);
  };

  var onIceCandidateToFirst = test.step_func(function(event) {
    // If event.candidate is null = no more candidates.
    if (event.candidate) {
      gSecondConnection.addIceCandidate(event.candidate);
    }
  });

  var onIceCandidateToSecond = test.step_func(function(event) {
    if (event.candidate) {
      gFirstConnection.addIceCandidate(event.candidate);
    }
  });

  var onRemoteTrack = test.step_func(function(event) {
    var videoTag = document.getElementById('remote-view');
    if (!videoTag.srcObject) {
      videoTag.srcObject = event.streams[0];
    }
  });

  // Returns a suitable error callback.
  function failed(function_name) {
    return test.unreached_func('WebRTC called error callback for ' + function_name);
  }

  // This function starts the test.
  test.step(function() {
    getNoiseStream({ video: true, audio: true })
      .then(test.step_func(getNoiseStreamOkCallback), failed('getNoiseStream'));
  });
</script>

</body>
</html>
