  /*
   *  File: moxi_video.js
   *  NameSpace: Moxi.Video
   *  Description: Used to place video content on Moxicom pages. The moxi_video.js is not
   *               automatically inititated with moci.js. A script tag with the moxi_video.js
   *               path and filename must be added to pages that will contain video content.
   *  Created: August 13, 2009
   *  Last Modified: August 28, 2009
   *  Design Document: http://home.digeo.com/groups/webdevelopment/Shared%20Documents/Design%20Docs/Moxi%20Video%20Specs.doc
  */
  
  ( function()
  {
    var ThisFunction = this;

    ThisFunction.XMLData = [];
    ThisFunction.VideoState;
    ThisFunction.index = 0;

    var MoxiSiteRoot = Moxi.SiteRoot;
    var VideoPlayer = null;
    var FlashFileID = null;
    var VideoPlayerConfig = Moxi.XMLRoot + "player_config.xml";
    var VideoTimeTracking = 0;
    var VideoTimeDuration = 0;

    var VideoTrackingTemplate = "video/{0}/timeviewed/{1}";
    var addControllerListener, addModelListener, addViewListener;

    // Private Functions

    function GetAttributes( a_Element )
    {
      var ReturnValue = {};
      var Attributes = a_Element.attributes;
      if( Attributes )
      {
        for( var i = 0; i < Attributes.length; i++ )
        {
          ReturnValue[Attributes[i].name] = Attributes[i].value;
        }
      }
      return ReturnValue;
    }

    function getPlaylist( a_XMLFilePath )
    {
      /*
        The XML data is a JSON object, contained within an array, representaion of the XML playlist.
        Unlike the data passed by the player, which contains only a subset of the actual XML,
        this contains ALL of the XML tags and attributes.

        The XMLData objects will map the following object values with these XML tags.

            XMLData 	              XML Tag
            author                	creator
            description	            annotation
            duration	              duration
            file	                  location
            link	                  info
      */
      $.ajax(
      {
        url: a_XMLFilePath,
        type: 'GET',
        dataType: 'xml',
        timeout: 1000,
        success: function( a_ResponseDoc )
        {
          var TrackObject, TrackAttributes, TrackChildren;
          $( a_ResponseDoc ).find( 'track' ).each( function()
          {
            TrackObject = {};
            TrackObject.attr = GetAttributes( this );
            $( this ).children().each( function()
            {
              NodeName = MapNodeName( this.nodeName );
              TrackObject[NodeName] = GetAttributes( this );
              TrackObject[NodeName].text = ( $( this ).text() )? $( this ).text().ParseHTML() : $( this ).text();
            });
            ThisFunction.XMLData.push( TrackObject );
          });
          if( isDefined( window.onPlaylistLoad ) )
          {
            window.onPlaylistLoad( ThisFunction.XMLData );
          }
        }
      });
    }
    
    function MapNodeName( a_nodeName )
    {
      var XMLFieldMap = {};
      XMLFieldMap.creator = 'author';
      XMLFieldMap.annotation = 'description';
      XMLFieldMap.duration = 'duration';
      XMLFieldMap.location = 'file';
      XMLFieldMap.info = 'link';
      if( XMLFieldMap[a_nodeName] )
      {
        return XMLFieldMap[a_nodeName];
      }
      return a_nodeName;
    }
    
    function TrackVideo()
    {
      if( VideoTimeTracking && ThisFunction.XMLData[ThisFunction.index].attr.gatrack )
      {
        var TimeVideoWasViewed = Math.round( VideoTimeTracking );
        var VideoTrackingPath = ThisFunction.XMLData[ThisFunction.index].attr.gatrack;
        Moxi.TrackEvent( VideoTrackingTemplate.format( VideoTrackingPath, TimeVideoWasViewed ) );
      }
    }

    // Public Methods

    ThisFunction.Load = function( a_Target, a_File, a_FlashVars, a_Width, a_Height )
    {
      FlashFileID = a_Target;
      var TargetElement = $( '#' + FlashFileID );
      a_Width = ( a_Width )? a_Width : TargetElement.width();
      a_Height = ( a_Height )? a_Height : TargetElement.height();
      a_Options = {};

      a_Options.wmode = ( a_Options.wmode )?a_Options.wmode : "transparent";
      a_Options.allowScriptAccess = ( a_Options.allowScriptAccess )?a_Options.allowScriptAccess : "sameDomain";
      a_Options.allowFullScreen = ( a_Options.allowFullScreen )?a_Options.allowFullScreen : "true";
      
      a_FlashVars.file = a_File;
      a_FlashVars.config = VideoPlayerConfig;
      a_FlashVars.id = FlashFileID;
      
      var attributes =
      {
        'id': FlashFileID,
        'name': FlashFileID
      };
      
      if( a_File.match( /\.xml$/ig ) )
      {
        getPlaylist( a_File );
      }
      swfobject.embedSWF( MoxiSiteRoot + "flash/player.swf", FlashFileID, a_Width, a_Height, "9", MoxiSiteRoot + "flash/expressInstall.swf", a_FlashVars, a_Options, attributes, ThisFunction.onSWFLoad );
    }
    
    ThisFunction.onSWFLoad = function( a_Event )
    {
      ///	<summary>
      ///   Called on both success or failure of embedding a SWF file.
      ///	</summary>
      ///	<param name="a_Event" type="Object">
      ///   Contains the following values
      ///   1: success - Boolean to indicate whether the embedding of a SWF was success or not.
      ///   2: id - String indicating the ID used in swfobject.embedSWF. 
      ///   3: ref - HTML object element reference ( returns undefined when success=false ). 
      ///	</param>
			if( !a_Event.success )
			{
			  $( '#' + a_Event.id ).css( 'background-color', '#000000' );
			  $( '#' + a_Event.id ).html( '<p>This website requires Flash Player 9 or higher and JavaScript enabled in your browser.</p><p>Visit <a href="http://get.adobe.com/flashplayer/">http://get.adobe.com/flashplayer/</a> to download the latest version.</p>' );
			}
			if( isDefined( window.onSWFLoad ) && Function.Is( window.onSWFLoad ) )
      {
        window.onSWFLoad( a_Event );
      }
    }

    ThisFunction.Play = function( a_VideoParam )
    {
      if( String.Is( a_VideoParam ) )
      {
        // a_VideoParam must contain a URL so we load it.
        VideoPlayer.sendEvent( 'LOAD', a_VideoParam );
      }
      else if( Number.Is( a_VideoParam ) )
      {
        // a_VideoParam must contain an integer corresponding to a position in the playlist so we play that index.
        VideoPlayer.sendEvent( 'ITEM', a_VideoParam );
      }
      else
      {
        // Toggle play/pause
        VideoPlayer.sendEvent( 'PLAY' );
      }
    }

    // Events

    ThisFunction.onVideoItem = function( a_Data )
    {
      ///	<summary>
      ///   Fired when the player switches to a new playlistitem. The new item will immediately start
      ///   playing. The currently playing item is always available through the item flashvar.
      ///	</summary>
      ///	<param name="a_Data" type="Object">
      ///   Contains the following values
      ///   1: index - Number: index of the new view in the playlist.
      ///	</param>
      TrackVideo();
      ThisFunction.index = a_Data.index;
      VideoTimeTracking = 0;
      if( isDefined( window.onVideoItem ) && Function.Is( window.onVideoItem ) )
      {
        window.onVideoItem( a_Data );
      }
    }

    ThisFunction.onVideoStop = function()
    {
      ///	<summary>
      ///   Fired when the player stops loading and playing. The playback state will turn to
      ///   IDLE and the position of a video will be set to 0. No parameters. 
      ///	</summary>
      TrackVideo();
      if( isDefined( window.onVideoStop ) && Function.Is( window.onVideoStop ) )
      {
        window.onVideoStop();
      }
    }

    ThisFunction.onVideoStateChange = function( a_Data )
    {
      ///	<summary>
      ///   Fired when the playback state of the video changes. Use this to check when a video has
      ///   started (newstate=BUFFERING), is paused (newstate=PAUSED) or finished (newstate=COMPLETED).
      ///   The current state is always available through the state flashvar.
      ///	</summary>
      ///	<param name="a_Data" type="Object">
      ///   Contains the following values
      ///   1. oldstate - String: the previous playback state ( IDLE, BUFFERING, PLAYING, PAUSED, COMPLETED ). 
      ///   2. newstate - String: the new playback state ( IDLE, BUFFERING, PLAYING, PAUSED, COMPLETED ).
      ///	</param>
      ThisFunction.VideoState = a_Data;
      if( isDefined( window.onVideoStateChange ) && Function.Is( window.onVideoStateChange ) )
      {
        window.onVideoStateChange( a_Data );
      }
    }

    ThisFunction.onVideoTimer = function( a_Data )
    {
      ///	<summary>
      ///   Fired when the playback position is changing (i.e. the videosound/image is playing).
      ///   It is fired with a resolution of 1/10 second, so there'll be a lot of events. This is
      ///   needed for tight timing with e.g. closed captioning.
      ///	</summary>
      ///	<param name="a_Data" type="Object">
      ///   Contains the following values
      ///   1. duration - Number: total duration of the file in seconds. Two and a half minutes
      ///                 correspond to a duration of 150.
      ///   2. position - Number: current playback position in the file, in seconds. Two and a
      ///                 half minutes correspond to a position of 150.
      ///	</param>
      if( ThisFunction.VideoState.newstate.Eq( 'PLAYING' ) )
      {
        if( a_Data.position )
        {
          VideoTimeDuration = a_Data.duration;
          VideoTimeTracking = a_Data.position;
        }
      }
      if( isDefined( window.onVideoTimer ) && Function.Is( window.onVideoTimer ) )
      {
        window.onVideoTimer( a_Data );
      }
    }
    
    ThisFunction.onVideoLoad = function()
    {
      ///	<summary>
      ///   Fired when the user wants to play the next playlistitem. No parameters.
      ///	</summary>
      if( isDefined( window.onVideoLoad ) && Function.Is( window.onVideoLoad ) )
      {
        window.onVideoLoad();
      }
    }
    
    // Video Player Called Function

    window.playerReady = function( a_Data )
    {
      ///	<summary>
      ///   This function is called when the player is succesfully instantiated.
      ///   When fired the VideoPlayer object is defined and all events listeners are initialized.
      ///	</summary>
      ///	<param name="a_Data" type="Object">
      ///   Contains the following values
      ///   1. id - String: ID of the player in the HTML DOM. Used by javascript to reference the player. 
      ///   2. client - String: A string representing the client the player runs in (e.g. FLASH WIN
      ///               9,0,115,0). 
      ///   3. version - String: A string representing the major version, minor version and revision
      ///               number of the player (e.g. 4.2.95).
      ///	</param>
      VideoPlayer = document.getElementById( a_Data.id );
      VideoPlayer.addControllerListener( "ITEM", "Moxi.Video.onVideoItem" );
      VideoPlayer.addControllerListener( "PLAY", "Moxi.Video.onVideoPlay" );
      VideoPlayer.addControllerListener( "STOP", "Moxi.Video.onVideoStop" );
      VideoPlayer.addModelListener( "STATE", "Moxi.Video.onVideoStateChange" );
      VideoPlayer.addModelListener( "TIME", "Moxi.Video.onVideoTimer" );
      VideoPlayer.addViewListener( "NEXT", "Moxi.Video.onVideoNext" );
      if( isDefined( window.onPlayerLoaded ) && Function.Is( window.onPlayerLoaded ) )
      {
        window.onPlayerLoaded( a_Data );
      }
    };
    
    window.onunload = function()
    {
      swfobject.removeSWF( FlashFileID );
    }

  }).add( 'Moxi.Video' );