<!DOCTYPE HTML>
<html>
<head>
<title>Test played member for media elements</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id='test'>
<script class="testbody" type='application/javascript'>

let manager = new MediaTestManager;

function finish_test(element) {
  removeNodeAndSource(element);
  manager.finished(element.token);
}

// Check that a file has been played in its entirety.
function check_full_file_played(element) {
  element.addEventListener('ended', (function(e) {
    let interval_count = e.target.played.length;
    is(interval_count, 1, element.token + ": played.length must be 1");
    is(element.played.start(0), 0, element.token + ": start time shall be 0");
    is(element.played.end(0), e.target.duration, element.token + ": end time shall be duration");
    finish_test(e.target);
  }));
}

var tests = [
// Without playing, check that player.played.length == 0.
{
  setup(element) {
    element.addEventListener("loadedmetadata", function() {
      is(element.played.length, 0, element.token + ": initial played.length equals zero");
      finish_test(element);
    });
  },
  name: "test1"
},
// Play the file, test the range we have.
{
  setup(element) {
    check_full_file_played(element);
    element.play();
  },
  name: "test2"
},

// Play the second half of the file, pause, play
// an check we have only one range.
{
  setup (element) {
    element.onended = function (e) {
      var t = e.target;
      t.onended = null;
      check_full_file_played(t);
      t.pause();
      t.currentTime = 0;
      t.play();
    };
    element.addEventListener("loadedmetadata", function() {
      element.currentTime = element.duration / 2;
      element.play();
    });
  },
  name: "test3"
},

// Play the first half of the file, seek back, while
// continuing to play. We shall have only one range.
{
  setup (element) {
    let onTimeUpdate = function() {
      if (element.currentTime > element.duration / 2) {
        info(element.token + ": currentTime=" + element.currentTime + ", duration=" + element.duration);
        element.removeEventListener("timeupdate", onTimeUpdate);
        element.pause();
        var oldEndRange = element.played.end(0);
        element.currentTime = element.duration / 4;
        is(element.played.end(0), oldEndRange,
           element.token + ": When seeking back, |played| should not be changed");
        element.play();
      }
    }
    element.addEventListener("timeupdate", onTimeUpdate);
    check_full_file_played(element);
    element.play();
  },
  name: "test4"
},

// Play and seek to have two ranges, and check that, as well a
// boundaries.
{
  setup (element) {
    let seekTarget = 0;
    let onTimeUpdate = function() {
      if (element.currentTime > element.duration / 2) {
        info(element.token + ": currentTime=" + element.currentTime + ", duration=" + element.duration);
        element.removeEventListener("timeupdate", onTimeUpdate);
        element.pause();
        // Remember seek target for later comparison since duration may change
        // during playback.
        seekTarget = element.currentTime = element.duration / 10;
        element.currentTime = seekTarget;
        element.play();
      }
    }

    element.addEventListener("loadedmetadata", function() {
      element.addEventListener("timeupdate", onTimeUpdate);
    });


    element.addEventListener("ended", (function() {
      if(element.played.length > 1) {
        is(element.played.length, 2, element.token + ": element.played.length == 2");
        is(element.played.start(1), seekTarget, element.token + ": we should have seeked forward by one tenth of the duration");
        is(element.played.end(1), element.duration, element.token + ": end of second range shall be the total duration");
      }
      is(element.played.start(0), 0, element.token + ": start of first range shall be 0");
      finish_test(element);
    }));

    element.play();
  },
  name: "test5"
},

// Play to create two ranges, in the reverse order. check that they are sorted.
{
  setup (element) {
    function end() {
      element.pause();
      let p = element.played;
      ok(p.length >= 1, element.token + ": There should be at least one range=" + p.length);
      is(p.start(0), seekTarget, element.token + ": Start of first range should be the sixth of the duration");
      ok(p.end(p.length - 1) > 5 * element.duration / 6, element.token + ": End of last range should be greater that five times the sixth of the duration");
      finish_test(element);
    }

    let seekTarget = 0;
    function pauseseekrestart() {
      element.pause();
      // Remember seek target for later comparison since duration may change
      // during playback.
      seekTarget = element.duration / 6;
      element.currentTime = seekTarget;
      element.play();
    }

    function onTimeUpdate_pauseseekrestart() {
      if (element.currentTime > 5 * element.duration / 6) {
        element.removeEventListener("timeupdate", onTimeUpdate_pauseseekrestart);
        pauseseekrestart();
        element.addEventListener("timeupdate", onTimeUpdate_end);
      }
    }

    function onTimeUpdate_end() {
      if (element.currentTime > 3 * element.duration / 6) {
        element.removeEventListener("timeupdate", onTimeUpdate_end);
        end();
      }
    }

    element.addEventListener("timeupdate", onTimeUpdate_pauseseekrestart);

    element.addEventListener('loadedmetadata', function() {
      element.currentTime = 4 * element.duration / 6;
      element.play();
    });
  },
  name: "test6"
},
// Seek repeatedly without playing. No range should appear.
{
  setup(element) {
    let index = 1;

    element.addEventListener('seeked', function() {
      index++;
      element.currentTime = index * element.duration / 5;
      is(element.played.length, 0, element.token + ": played.length should be 0");
      if (index == 5) {
        finish_test(element);
      }
    });

    element.addEventListener('loadedmetadata', function() {
      element.currentTime = element.duration / 5;
    });
  },
  name: "test7"
},
// Play for a bit, then seek to the end: two ranges when "ended" is received.
// Load another resource (invalid): no range
// Load another resource (valid): still no range
{
  setup(element) {
    let index = 1;
    let seeked = false;

    element.addEventListener('timeupdate', function() {
      index++;
      if (index == 2) {
        is(element.played.length, 1);
        element.currentTime = element.currentTime + element.duration / 100;
      }
      if (seeked) {
        is(element.played.length, 2, "After seeking, played.length should be 2");
      }
    });
    element.addEventListener('seeked', function() {
      seeked = true;
    });
    element.addEventListener('ended', function() {
      // For very short media file, timing is unreliable, it can be that the
      // file has finished playing, before the seek, and so there is only one
      // range in `played`.
      if (seeked) {
        is(element.played.length, 2, element.token + "After ended, played.length should be 2");
      } else {
        is(element.played.length, 1, element.token + "After ended, a short media file played.length should be 1 if it has ended before the seek");
      }
      let src_bck = element.src;
      element.src = "bogus.duh";
      is(element.played.length, 0, "After subsequent invalid load, played.length should be 0");
      element.src = src_bck;
      is(element.played.length, 0, "After subsequent valid load, played.length should be 0");
      finish_test(element);
    });
    element.addEventListener('loadedmetadata', function() {
      element.play();
    });
  },
  name: "test8"
}
];

function createTestArray() {
  var A = [];
  for (var i=0; i<tests.length; i++) {
    for (var k=0; k<gPlayedTests.length; k++) {
      var t = {};
      t.setup = tests[i].setup;
      t.name = tests[i].name + "-" + gPlayedTests[k].name;
      t.type = gPlayedTests[k].type;
      t.src = gPlayedTests[k].name;
      A.push(t);
    }
  }
  return A;
}

function startTest(test, token) {
  var elemType = getMajorMimeType(test.type);
  var element = document.createElement(elemType);
  element.src = test.src;
  element.token = token;
  element.preload = "metadata";
  test.setup(element);
  manager.started(token);

  // Log events for debugging.
  var events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
                "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort",
                "waiting", "pause"];
  function logEvent(e) {
    var v = e.target;
    info(v.token + ": got " + e.type);
  }
  events.forEach(function(e) {
    element.addEventListener(e, logEvent);
  });

}


manager.runTests(createTestArray(), startTest);

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