<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Testing basic video exchange from offerer to receiver</title>
        <script src="../resources/testharness.js"></script>
        <script src="../resources/testharnessreport.js"></script>
    </head>
    <body>
        <video id="localVideo" autoplay playsInline width="320" height="240"></video>
        <video id="video" autoplay playsInline width="320" height="240"></video>
        <canvas id="canvas1" width="320" height="240"></canvas>
        <canvas id="canvas2" width="320" height="240"></canvas>
        <canvas id="canvas3" width="320" height="240"></canvas>
        <script src ="routines.js"></script>
        <script>
function isVideoBlack(id)
{
    var canvas = document.getElementById(id);
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);

    imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
    data = imageData.data;
    for (var cptr = 0; cptr < canvas.width * canvas.height; ++cptr) {
        // Approximatively black pixels.
        if (data[4 * cptr] > 10 || data[4 * cptr + 1] > 10 || data[4 * cptr + 2] > 10)
            return false;
    }
    return true;
}

function pollVideoBlackCheck(expected, id, resolve, reject, counter)
{
    if (isVideoBlack(id) === expected) {
        resolve();
        return;
    }

    if (!counter)
        counter = 0;
    else if (++counter > 40) {
        reject("test for " + id + " timed out");
        return;
    }
    setTimeout(() => pollVideoBlackCheck(expected, id, resolve, reject, counter), 100);
}

function checkVideoBlack(expected, id)
{
    return new Promise((resolve, reject) => {
        pollVideoBlackCheck(expected, id, resolve, reject);
    });
}

var track;
var remoteTrack;
promise_test((test) => {
    if (window.testRunner)
        testRunner.setUserMediaPermission(true);

    return navigator.mediaDevices.getUserMedia({video: {width: 320, height: 240, facingMode: "environment"}}).then((localStream) => {
        track = localStream.getVideoTracks()[0];
        track.enabled = false;
        localVideo.srcObject = localStream;
        return new Promise((resolve, reject) => {
            createConnections((firstConnection) => {
                firstConnection.addTrack(track, localStream);
            }, (secondConnection) => {
                secondConnection.ontrack = (trackEvent) => {
                    remoteTrack = trackEvent.track;
                    resolve(trackEvent.streams[0]); 
                };
            });
            setTimeout(() => reject("Test timed out"), 5000);
        });
    }).then((remoteStream) => {
        video.srcObject = remoteStream;
        return video.play();
    });
}, "Setting video exchange");

promise_test((test) => {
    return checkVideoBlack(true, "canvas1");
}, "Track is disabled, video should be black");

promise_test((test) => {
    track.enabled = true;
    return checkVideoBlack(false, "canvas2");
}, "Track is enabled, video should not be black");

        </script>
    </body>
</html>
