var MEDIA_THRESHOLD = 300; // ms

var g_lastPositionMs = 0;

// 0: Stopped
// 1: Paused
// 2: Playing
var g_playerState = 0;
var g_masterSyncingToClip = -1;
var g_clipSyncingToMaster = -1;
var g_currentClipPlayer   = -1;

var g_pausedPositionValid = false;

var g_startPosition = 0;

var g_controlPlayerChecked = 0;

var g_controlWasPlaying = false;
var g_controlIsSliding = false;

var g_controlIsMuted = false;
var g_controlVolumeBackup = 50;

var g_controlHasPlayedOnce = false;

function control_getClipPlayer(playerNumber)
{
  if (!isNS4)
  {
    var clipPlayer = getEmbeddedObject('', 'ClipPlayer' + playerNumber);
    return clipPlayer;
  }
  else
  {
    var clipPlayer = document.layers["ClipLayer" + playerNumber].document.embeds["ClipPlayer" + playerNumber];
    return clipPlayer;
  }
}

function control_getMasterPlayer()
{
  var masterPlayer = getEmbeddedObject('', 'MasterPlayer');
  return masterPlayer;
}

function control_getCurrentPosition(player)
{
  if (isNS4 || isOpera)
    return Math.round(player.GetCurrentPosition() * 1000);
  else
    return Math.round(player.CurrentPosition * 1000);
}

function control_setCurrentPosition(player, msTime)
{
  if (isNS4 || isOpera)
    player.SetCurrentPosition(msTime / 1000.0);
  else
    player.CurrentPosition = msTime / 1000.0;
}

function control_beginSlide()
{
  g_controlIsSliding = true;
  g_controlWasPlaying = control_isPlaying();
  if (g_controlWasPlaying)
    control_stop();
}

function control_endSlide()
{
  g_controlIsSliding = false;
  if (g_controlWasPlaying)
    control_playPause();
}

function controlInit()
{
  // Position the clips layers
  var clipsLeft = layout_getSlidesLeft();
  var clipsTop  = layout_getSlidesTop();
  for (var i=0; i<g_numOfClips; ++i)
  {
    var layerStyle = getHtmlObject('', 'ClipLayer' + i, '', true, true);
    var deltaW = (g_slidesWidth - g_clipEntries[i].width) / 2;
    var deltaH = (g_slidesHeight - g_clipEntries[i].height) / 2;
    if (deltaW < 0)
      deltaW = 0;
    if (deltaH < 0)
      deltaH = 0;
    layerStyle.left = clipsLeft + deltaW;
    layerStyle.top  = clipsTop  + deltaH;
  }

  layout_setPlayIsPause(false);
  layout_enableControl("play", true);
  setInterval("control_onSync()", 200);
  setTimeout("control_notifyCurrentTime(0);", 500);
}

function control_isPlayerVisible(player, playerNumber)
{
  var playerStyle = getHtmlObject('', 'ClipLayer' + playerNumber, '', true, true);
  return (playerStyle.visibility != 'hidden' &&
          playerStyle.visibility != 'hide');
}

function control_setVisible(player, playerNumber, bVisible)
{
  var playerStyle = getHtmlObject('', 'ClipLayer' + playerNumber, '', true, true);
  if (bVisible)
    playerStyle.visibility = 'visible';
  else
    playerStyle.visibility = 'hidden';

  if (!isNS4 && player)
  {
    if (bVisible)
      player.style.visibility = 'visible';
    else
    {
      player.style.visibility = 'hidden';
    }
  }
}

function control_notifyCurrentTime(valueMs)
{
  g_lastPositionMs = valueMs;
  
  var playerToBeVisible = -1;
  for (var i=0; i<g_numOfClips && playerToBeVisible == -1; ++i)
  {
    if (valueMs >= g_mediaStartTimes[i+1] &&
        valueMs < g_mediaStartTimes[i+1] + g_mediaDurations[i+1])
    {
      playerToBeVisible = i;
    }
  }

  for (var i=0; i<g_numOfClips; ++i)
  {
    var clipPlayer = control_getClipPlayer(i); //document.getElementById('ClipPlayer' + (i+1));
    if (i == playerToBeVisible)
    {
      if (!control_isPlayerVisible(clipPlayer, playerToBeVisible))
        control_setVisible(clipPlayer, playerToBeVisible, true);
    }
    else
    {
      if (control_isPlayerVisible(clipPlayer, i))
      {
        control_setVisible(clipPlayer, i, false);
        // Don't try to stop a clip player which never has been
        // started. Will lead to severe JavaScript errors under
        // certain circumstances.
        if (!control_isPlayerStopped(clipPlayer) && g_controlHasPlayedOnce)
        {
          clipPlayer.Stop(); 
        }
      }
    }
  }

  layout_updateTime(valueMs);
  g_currentClipPlayer = playerToBeVisible;

  // this method is in slides.js
  slides_notifyNewMediaPlayerPosition(valueMs);
  
  return playerToBeVisible;
}

function control_playPause()
{
  if (!g_controlHasPlayedOnce)
    g_controlHasPlayedOnce = true;

  // No pause/play in sync mode
  if (g_masterSyncingToClip >= 0 ||
      g_clipSyncingToMaster >= 0)
  {
    return;
  }
    
  if (g_playerState != 2)
  {
    g_playerState = 2;

    var positionMs = g_lastPositionMs;
    var masterPlayer = control_getMasterPlayer();

	  if (control_isPlayerPlaying(masterPlayer))
	  {
	    // Emergency stop. Something's wrong.
	    control_stop();
	    return;
	  }
    
    if (!control_isPlayerPaused(masterPlayer) || !g_pausedPositionValid)
    {
       control_setCurrentPosition(masterPlayer, positionMs);
       g_startPosition = positionMs;

       layout_displayIsBuffering(true);
       layout_enableControl("play", false);
    }
    else
    {
      // Master player is paused and the slider was not 
      // touched; kick off the clip player, too, if possible.
      if (g_currentClipPlayer >= 0)
      {
        var clipPlayer = control_getClipPlayer(g_currentClipPlayer); //document.getElementById('ClipPlayer' + (g_currentClipPlayer + 1));
        if (control_isPlayerPaused(clipPlayer))
        {
          clipPlayer.Play();
          // In case of NS4: focus the popup
          // control_setVisible(clipPlayer, g_currentClipPlayer, true);
        }
        else
        {
          // No good. Stop the clip player just in case.
          clipPlayer.Stop();
        }
      }
    }
    masterPlayer.Play();
    
    layout_setPlayIsPause(true);
  }
  else // player state is 2 = playing
  {
    // Pause it
    g_playerState = 1;

    var masterPlayer = control_getMasterPlayer();

    if (control_isPlayerPlaying(masterPlayer))
    {
      g_lastPositionMs = control_getCurrentPosition(masterPlayer);
      g_pausedPositionValid = true;

      masterPlayer.Pause();
      if (g_currentClipPlayer >= 0)
		{
        var clipPlayer = control_getClipPlayer(g_currentClipPlayer);
        if (control_isPlayerPlaying(clipPlayer))
		  {
          clipPlayer.Pause();
        }
        else
		  {
          // The clip was not playing when it should have,
          // Emergency stop!
          control_stop();
          return;
        }
      }

      layout_setPlayIsPause(false);
    }
  }
}

function control_stop()
{
  var masterPlayer = control_getMasterPlayer();
  // Stop the master player if not already stopped
  if (!control_isPlayerStopped(masterPlayer))
    masterPlayer.Stop();

  // Now stop all running clip players (should not be more
  // than one).
  for (var i=0; i<g_numOfClips; ++i)
  {
    var clipPlayer = control_getClipPlayer(i);
    if (!control_isPlayerStopped(clipPlayer))
    {
      clipPlayer.Stop();
    }
  }
  
  g_playerState = 0;
  // Get out of any sync modes.
  g_masterSyncingToClip = -1;
  g_clipSyncingToMaster = -1;
  
  layout_enableControl("stop", false);
  layout_enableControl("play", true);
  layout_setPlayIsPause(false);
  layout_displayIsBuffering(false);
}

function control_isPlayerPlaying(player)
{
  // Is playing if is buffering or is playing
  if (isNS4 || isOpera)
    return (player.GetPlayState() == 2 ||
            player.GetPlayState() == 3);
  else
    return (player.PlayState == 2 ||
            player.PlayState == 3);
}

function control_isPlayerStopped(player)
{
  // Is playing if is buffering or is playing
  if (isNS4 || isOpera)
    return (player.GetPlayState() == 0);
  else
    return (player.PlayState == 0);
}

function control_isPlayerPaused(player)
{
  if (isNS4 || isOpera)
    return (player.GetPlayState() == 1);
  else
    return (player.PlayState == 1);
}
  

function control_isPlaying()
{
  return (control_isPlayerPlaying(control_getMasterPlayer()));
}

function control_getTimeMs()
{
  return g_lastPositionMs;
}

function control_seekTime(valueMs)
{
  var masterPlayer = control_getMasterPlayer();
  var wasPlaying = control_isPlayerPlaying(masterPlayer);
  if (wasPlaying)
    control_stop();
  g_pausedPositionValid = false;
  layout_updateTime(valueMs);
  control_notifyCurrentTime(valueMs);
  if (wasPlaying)
    setTimeout("control_playPause()", 200);
}

function control_checkPlayers()
{
  g_controlPlayerChecked++;

  if (isNS4)
    return;

  if (!isIE)
  {
    var masterPlayer = control_getMasterPlayer();
    var success = false;
    if (masterPlayer != null)
    {
       var playFunc = masterPlayer.Play;
       if (playFunc != null)
          success = true;
    }

    if (!success)
    {
      // That went wrong
      if (g_controlPlayerChecked < 5)
        setTimeout("control_checkPlayers()", 200);
      else
      {
        alert(g_playerWarningMessage);
        layout_enableControl("play", false);
        layout_enableControl("end", false);
        layout_enableControl("home", false);
        layout_enableControl("back", false);
        layout_enableControl("forward", false);
        layout_enableControl("mute", false);
      }
    }
  }
  else
  {
    g_controlPlayerChecked = 1;
  }
}

function control_onSync()
{
  if (g_controlPlayerChecked == 0)
    control_checkPlayers();

  // Is invoked every 250 ms.
  if (g_playerState != 2) // not playing currently
    return;

  // Get the master player        
  var masterPlayer = control_getMasterPlayer();
  
  // We think we're playing. Are we?
  if (!control_isPlayerPlaying(masterPlayer))
  {
    // Are we syncing the master to a clip?
    if (g_masterSyncingToClip >= 0)
    {
      var clipPlayer = control_getClipPlayer(g_masterSyncingToClip);
      // Check that clip's time.
      var clipTimeMs = g_mediaStartTimes[g_masterSyncingToClip + 1] + control_getCurrentPosition(clipPlayer);
      var currentTimeMs = control_getCurrentPosition(masterPlayer);
      if (clipTimeMs >= currentTimeMs - MEDIA_THRESHOLD)
      {
        // The clip player has caught up, restart master player
        masterPlayer.Play();
        g_masterSyncingToClip = -1;

        layout_displayIsBuffering(false);
        layout_setPlayIsPause(true);
        layout_enableControl("play", true);
        return;
      }
      else
      {
        return;
      }
    }
    else
    {
      // No sync, something has gone wrong.
      // Emergency stop
      control_stop();
      return;
    }
  }
  
  // Are we syncing a clip to the master?
  if (g_clipSyncingToMaster >= 0)
  {
    var clipPlayer = control_getClipPlayer(g_clipSyncingToMaster);
    // Check that clip's time.
    var clipTimeMs = g_mediaStartTimes[g_clipSyncingToMaster + 1] + control_getCurrentPosition(clipPlayer);
    var currentTimeMs = control_getCurrentPosition(masterPlayer);
    if (currentTimeMs >= clipTimeMs - MEDIA_THRESHOLD)
    {
      // The master player has caught up, restart clip player
      clipPlayer.Play();
      // For NS4:
      // control_setVisible(clipPlayer, g_clipSyncingToMaster, true);
      g_clipSyncingToMaster = -1;

      layout_displayIsBuffering(false);
      layout_setPlayIsPause(true);
      layout_enableControl("play", true);
      return;
    }
    else
    {
      return;
    }
  }
  
  // What time is it?
  var currentTimeMs = control_getCurrentPosition(masterPlayer);
  var visiblePlayer = control_notifyCurrentTime(currentTimeMs);
  layout_updateTime(currentTimeMs);
  slides_notifyNewMediaPlayerPosition(currentTimeMs);

  // Were we buffering but aren't anymore?
  if (g_startPosition != -1 && g_startPosition != currentTimeMs)
  {
    g_startPosition = -1;
    layout_displayIsBuffering(false);
    layout_enableControl("play", true);
    //getVideoFrameObject('statusDisplay').innerHTML = '';
  }
  
  // Is there a player visible right now?
  if (visiblePlayer >= 0)
  {
    var clipPlayer = control_getClipPlayer(visiblePlayer);
    
    // Now check sync on clip player
    if (control_isPlayerPlaying(clipPlayer))
    {
      var clipPos = g_mediaStartTimes[visiblePlayer + 1] + control_getCurrentPosition(clipPlayer);
      var deltaMs = currentTimeMs - clipPos;
      if (Math.abs(deltaMs) > MEDIA_THRESHOLD)
      {
        layout_enableControl("play", false);
        layout_displayIsBuffering(true);

        // We're beyond the Media threshold, do something
        if (deltaMs > 0)
        {
          // We need to pause the master player to let
          // the clip player catch up.
        	g_masterSyncingToClip = visiblePlayer;
        	masterPlayer.Pause();
        }
        else
        {
          // The master player is behind, let's pause
          // the clip player for a while
          g_clipSyncingToMaster = visiblePlayer;
          clipPlayer.Pause();
        }
      }
    }
    else
    {
      control_setCurrentPosition(clipPlayer, currentTimeMs - g_mediaStartTimes[visiblePlayer + 1]);
      clipPlayer.Play();
      // For NS4:
      // control_setVisible(clipPlayer, visiblePlayer, true);
    }
  }
}

function control_setVolume(relVol)
{
  var targVolume = -10000;
  if (relVol > 0)
  {
    var logVol = Math.log(relVol / 100.0);
    if (logVol > -4)
      targVolume = Math.ceil(logVol * 2500);
  }
  
  var masterPlayer = control_getMasterPlayer(); //document.getElementById('MasterPlayer');
  if (isNS4 || isOpera)
    masterPlayer.SetVolume(targVolume);
  else
    masterPlayer.Volume = targVolume;
}

function control_getVolume()
{
  var masterPlayer = control_getMasterPlayer(); //document.getElementById('MasterPlayer');
  var playerVol = 0;
  if (isNS4 || isOpera)
    playerVol = masterPlayer.GetVolume();
  else
    playerVol = masterPlayer.Volume;

  var volValue = 0;
  if (playerVol > -10000)
    volValue = Math.round(100.0 * Math.exp(playerVol / 2500));

  return volValue;
}

function control_mute()
{
  if (g_controlIsMuted)
  {
    g_controlIsMuted = false;
    control_setVolume(g_controlVolumeBackup);
  }
  else
  {
    g_controlIsMuted = true;
    g_controlVolumeBackup = control_getVolume();
    control_setVolume(0);
  }

  layout_setIsMuted(g_controlIsMuted);
}

