text: /* 
   * NarrationManager.js
   * Keynote HTML Player
   * 
   * Created by Tungwei Cheng
   * Copyright (c) 2013 Apple Inc. All rights reserved.
   */
  
  var NarrationManager = Class.create({
      initialize: function(recording) {
          // recording movies in an array 
          this.movieSegments = recording.movieSegments;
  
          // total time of this recording
          this.duration = recording.duration;
  
          // navigation, movie and pause in eventTracks array
          this.eventTracks = recording.eventTracks;
  
          // current navigation event index
          this.currentNavigationEventIndex = 0;
  
          // last scene index
          this.lastSceneIndex = 0;
  
          for (var i = 0, length = this.eventTracks.length; i < length; i++) {
              var eventTrack = this.eventTracks[i];
  
              if (eventTrack.type === "navigation") {
                  this.navigationEvents = eventTrack.events;
              } else if (eventTrack.type === "movie") {
                  this.movieEvents = eventTrack.events;
              } else if (eventTrack.type === "pause") {
                  this.pauseEvents = eventTrack.events;
              }
          }
  
      },
  
      start: function() {
          // set up media resources
          var audio = new Audio();
          audio.src = "../" + this.movieSegments[0].url;
  
          // observe play event
          Event.observe(audio, "playing", this.handleAudioDidStart.bind(this));
          Event.observe(audio, "ended", this.handleAudioDidEnd.bind(this, 0));
  
          audio.play();
      },
  
      handleAudioDidStart: function() {
          // audio has started, now navigate to the first navigation event
          setTimeout(this.navigate(this.navigationEvents[0], true), 100);
      },
  
      handleAudioDidEnd: function(audioIndex) {
          var nextAudioIndex = audioIndex + 1;
  
          if (this.movieSegments[nextAudioIndex]) {
              var audio = new Audio();
              audio.src = "../" + this.movieSegments[nextAudioIndex].url;
              audio.play();
  
              Event.stopObserving(audio, "ended");
              Event.observe(audio, "ended", this.handleAudioDidEnd.bind(this, nextAudioIndex));
          }
      },
  
      navigate: function(event, startup) {
          var sceneIndex = this.sceneIndexFromNavigationEvent(event);
  
          if (event.animationPhase === "start") {
              // if event's slideIndex has been changed from lastScene's slide
              // check to see if this is our next scene to play
              var isNextScene = false;
  
              if (gShowController.script.loopSlideshow) {
                  if (this.lastSceneIndex === gShowController.script.numScenes - 1) {
                      if (sceneIndex === 0) {
                          isNextScene = true;
                      }                    
                  }
              } else {
                  if (this.lastSceneIndex + 1 === sceneIndex) {
                      isNextScene = true;
                  }
              }
  
              if (isNextScene) {
                  if (gShowController.state ===  kShowControllerState_IdleAtInitialState) {
                      gShowController.playCurrentScene();
                  } else if (gShowController.state ===  kShowControllerState_IdleAtFinalState) {
                      gShowController.jumpToScene(this.lastSceneIndex, true);
                  }
              } else {
                  // this is the slide we are jumping to
                  var slideIndexToJump = gShowController.scriptManager.slideIndexFromSceneIndex(sceneIndex);
                  var sceneIndexOfHyperlink = this.lastSceneIndex;
  
                  // get hyperlink from slide, find the first occurrence of slideId in hyperlinks
                  var hyperlinks = gShowController.script.events[sceneIndexOfHyperlink].hyperlinks;
                  var hyperlink;
                  var hyperlinkEvent;
  
                  for (var i = 0, length = hyperlinks.length; i < length; i++) {
                      hyperlink = hyperlinks[i];
                      hyperlinkEvent = hyperlink.events[event.slide];
  
                      if (hyperlinkEvent) {
                          break;
                      }
                  }
  
                  if (hyperlink) {
                      // call jumpToHyperlinkSlide to play hyperlink transition
                      gShowController.jumpToHyperlinkSlide(slideIndexToJump, hyperlink);
                  } else {
                      // if no hyperlink event is found for any reason, we still want to jump 
                      gShowController.jumpToScene(sceneIndex, false);
                  }
              }
          } else if (event.animationPhase === "none" && startup == null) {
              gShowController.jumpToScene(sceneIndex, false);                
          }
  
          // if there is any more event then set it to run next
          var nextEvent = this.navigationEvents[this.currentNavigationEventIndex + 1];
  
          if (nextEvent == null) {
              return;
          }
  
          // set timeout to navigate to next event
          var duration =  nextEvent.startTime - event.startTime;
          setTimeout(this.navigate.bind(this, nextEvent), duration * 1000);
  
          this.lastSceneIndex = sceneIndex;
          this.currentNavigationEventIndex = this.currentNavigationEventIndex + 1;
      },
  
      handleCurrentSceneDidComplete: function(sceneIndexToJump) {
          // scene did complete, jump to next scene so we have more time to set it up
          gShowController.jumpToScene(sceneIndexToJump, false);
      },
  
      sceneIndexFromNavigationEvent: function(event) {
          // return sceneIndex from navigation event
          var slideId = event.slide;
          var slideList = gShowController.script.slideList;
          var newSlideIndex = -1;
  
          for (var i = 0, length = slideList.length; i < length; i++) {
              if (slideList[i] === slideId) {
                  newSlideIndex = i;
                  break;
              }
          }
  
          var sceneIndex = gShowController.scriptManager.sceneIndexFromSlideIndex(newSlideIndex);
          var newSceneIndex = event.eventIndex + sceneIndex;
  
          return newSceneIndex;
      },
  
      slideIndexFromSlideId: function(slideId) {
          var slideList = gShowController.slideList;
          var slideIndex = -1;
  
          for (var i = 0, length = slideList.length; i < length; i++) {
              if (slideList[i] === slideId) {
                  slideIndex = i;
                  break;
              }
          }
  
          return slideIndex;
      }
  });
  