<!DOCTYPE html>
<html lang='en-US'>
  <head>
    <title>EME playback test application</title>
  </head>
  <body style='font-family:"Lucida Console", Monaco, monospace; font-size:14px' onload="start()">
    <i>Clearkey works only with content encrypted using bear key.</i><br><br>
    <table>
    <tr title='URL param mediaFile=...'>
      <td><label for='mediaFile'>Encrypted video URL:</label></td>
      <td><input id='mediaFile' type='text' size='64'></td>
    </tr>
    <tr title='URL param licenseServerURL=...'>
      <td><label for='licenseServer'>License sever URL:</label></td>
      <td><input id='licenseServer' type='text' size='64'></td>
    </tr>
    <tr title='URL param keySystem=...'>
      <td><label for='keySystemList'>Key system:</label></td>
      <td><select id='keySystemList'></select></td>
    </tr>
    <tr title='URL param mediaType=...'>
      <td><label for='mediaTypeList'>Media type:</label></td>
      <td><select id='mediaTypeList'></select></td>
    </tr>
    <tr title='URL param useMSE=1|0'>
      <td><label for='useMSE'>Load media by:</label></td>
      <td>
        <select id='useMSE'>
          <option value='true' selected='selected'>MSE</option>
          <option value='false'>src</option>
        </select>
      </td>
    </tr>
    </table>
    <br>
    <button onclick='start();'>Play</button>
    <br><br>
    Decoded fps: <span id='decodedFPS'></span>
    <br>
    Dropped fps: <span id='droppedFPS'></span>
    <br>
    Total dropped frames: <span id='droppedFrames'></span>
    <br><br>
    <table>
    <tr>
      <td valign='top'><span id='video'></span></td>
      <td valign='top'>
        <label for='logs' onclick="toggleDisplay('logs');"><i>Click to toggle logs visibility (newest at top).</i><br></label>
        <div id='logs' style='overflow: auto; height: 480px; width: 480px; white-space: nowrap; display: none'></div>
      </td>
    </tr>
    </table>
    <div></div>
  </body>
  <script src='eme_player_js/app_loader.js' type='text/javascript'></script>
  <script type='text/javascript'>
    var testConfig;
    var emeApp;
    var player;
    var heartbeatCount = 0;

    function getTimeRanges(range) {
      const result = [];
      for (let i = 0; i < range.length; i++) {
        result.push(`[${range.start(i)},${range.end(i)}]`);
      }
      return '[' + result.join(', ') + ']';
    }

    function getVideoStatus(video) {
      if (video == null) {
        return 'null';
      }
      const result = [];
      result.push(`paused: ${video.paused}`);
      result.push(`ended: ${video.ended}`);
      result.push(`currentTime: ${video.currentTime}`);
      result.push(`duration: ${video.duration}`);
      result.push(`buffered: ${getTimeRanges(video.buffered)}`);
      result.push(`played: ${getTimeRanges(video.played)}`);
      if (video.error) {
        result.push(`error: {${video.error.code},${video.error.message}}`);
      }
      return result.join(', ');
    }

    function initApp() {
      testConfig = new TestConfig();
      testConfig.loadQueryParams();
      // Update document with test configuration values.
      emeApp = new EMEApp(testConfig);
      setInterval(function () {
                      Utils.timeLog('heartbeat #' + ++heartbeatCount +
                                    ' video: ' + getVideoStatus(player.video));
                  }, 1000);
    }

    function onTimeUpdate(e) {
      var video = e.target;
      Utils.timeLog('timeupdate @ ' + video.currentTime);
      if (video.currentTime < 1)
        return;

      Utils.timeLog('waiting for video to end.');
      video.removeEventListener('ended', Utils.failTest);
      Utils.installTitleEventHandler(video, 'ended');
      video.removeEventListener('timeupdate', onTimeUpdate);
    }

    function onFirstPlayEnded(e) {
      Utils.timeLog('First play ended.');
      var video = e.target;
      video.removeEventListener('ended', onFirstPlayEnded);
      video.removeEventListener('abort', Utils.failTest);

      // Reset src (to same video again).
      PlayerUtils.setVideoSource(player);

      // Play the video a second time.
      Utils.timeLog('Playing second time.');
      play(video, false);
    }

    function onLogEvent(e) {
      Utils.timeLog('Event: ' + e.type);
    }

    function onVisibilityChange(e) {
      Utils.timeLog('Event: ' + e.type + ', hidden: ' + document.hidden);
    }

    function onEnded(e) {
      Utils.timeLog('Event: ' + e.type);
      PlayerUtils.removeSession(player).then(function() {
        Utils.setResultInTitle('ENDED');
      }).catch(function(error) {
        Utils.timeLog(error);
        Utils.failTest('Failed PlayerUtils.removeSession');
      });
    }

    function play(video, playTwice) {
      Utils.timeLog('Starting play, hidden: ' + document.hidden);
      video.addEventListener('canplay', onLogEvent);
      video.addEventListener('load', onLogEvent);
      video.addEventListener('playing', onLogEvent);
      video.addEventListener('play', onLogEvent);
      video.addEventListener('canplaythrough', onLogEvent);
      video.addEventListener('stalled', onLogEvent);
      video.addEventListener('waiting', onLogEvent);
      video.addEventListener('waitingforkey', onLogEvent);
      document.addEventListener('visibilitychange', onVisibilityChange);
      Utils.resetTitleChange();
      if (playTwice) {
        // Wait for the first play to complete.
        video.addEventListener('ended', onFirstPlayEnded);
        return video.play();
      }
      // Ended should not fire before onTimeUpdate.
      video.addEventListener('ended', Utils.failTest);
      video.addEventListener('timeupdate', onTimeUpdate);
      return video.play();
    }

    function toggleDisplay(id) {
      var element = document.getElementById(id);
      if (!element)
        return;
      if (element.style['display'] != 'none')
        element.style['display'] = 'none';
      else
        element.style['display'] = '';
    }

    function start() {
      initApp();  
      // TODO(jrummell): Support setMediaKeys() after play().
      // See http://crbug.com/675011
      emeApp.createPlayer()
          .then(function(p) {
              player = p;
              return play(player.video, testConfig.playTwice);
          }).catch(function(error) {
              Utils.timeLog(error);
              Utils.failTest('Unable to play video.');
          });
    }
  </script>
</html>
