
var g_dTabBarOffsetHeight = 20;
var g_dImageAspect = (4/3);
var g_dTabViewerContentPadding = 10;

// tab viewer for object and image streams
function TabViewer(el, viewer, useLargeTabs)
{
    var m_el = el;
    var m_pViewer = viewer;
    var m_pLastStatus = null;
    
    // height passed in to onresize - available height for content - width recorded during onresize
    var m_dContentHeightAvailable;
    var m_dContentWidthAvailable;
    var m_dContentWidth;
    var m_dContentHeight;
    
    // create our tab control
    var m_pTabControl = new TabControl(document.getElementById( "tabViewerBar" ), OnSelectView, useLargeTabs);
    
    // create our content div
    var m_elContent = document.getElementById( "tabContent" );
    
    var m_arrPlayers = new Object();
    var m_arrViews = null;
    var m_pSelectedView = null;
    
    // create our object video player
    var el = CreateChildElement(m_elContent, "div", "contentArea");
    if( g_bUsingSilverlight )
        m_arrPlayers["Object"] = new SilverlightVideoPlayer(el, "objectVideoPlayer");
    else
        m_arrPlayers["Object"] = new VideoPlayer(el, "objectVideoPlayer", true);
    viewer.SetObjectVideoPlayer( m_arrPlayers["Object"] );
    m_arrPlayers["Object"].SetVisible(false);

    // create our image viewer
    el = CreateChildElement(m_elContent, "div", "contentArea");
    m_arrPlayers["Image"] = new ImageViewer(el);
    m_arrPlayers["Image"].SetVisible(false);


    // callback for clicking on tabs
    // can pass in null to hide the current view
    function OnSelectView(pView)
    {
        // if the current player no longer is needed then hide it
        if( m_pSelectedView && (!pView || m_pSelectedView.Type != pView.Type) )
        {
            m_arrPlayers[m_pSelectedView.Type].SetVisible( false );
        }
        
        if (m_pSelectedView != pView)
        {
            m_pSelectedView = pView;
            
            // if we don't have a selected view, return
            if( !m_pSelectedView )
            {
                return;
            }
            
            // show player for this view
            m_arrPlayers[pView.Type].SetVisible( true );
            
            // resize the entire viewer
            m_pViewer.Resize();
            
            // set the view if needed by this view type
            m_arrPlayers[pView.Type].Initialize( pView, null, viewer.OnObjectVideoPlayStateChanged );
            if( m_pLastStatus )
            {
                m_arrPlayers[pView.Type].UpdateStatus( m_pLastStatus, true );
            }
        }
    }
    
    // set our array of views
    this.SetViews = function SetViews( arrViews )
    {
        // keep track of array and pass into our tab control
        m_arrViews = arrViews;
        
        // set the initial enabled/disabled properties for our views - use time of 0
        this.EnableDisableViews( 0 );
        
        m_pTabControl.SetViews( arrViews );
    }
    
    this.SelectStream = function( streamID )
    {
        m_pTabControl.SelectFirstViewWithData( "StreamID", streamID );
    }
    
    // enable and disable tabs based on the given time
    this.EnableDisableViews = function( fTime )
    {
        for( var p in m_arrViews )
        {
            var pView = m_arrViews[p];
            if( pView.RelativeStart != null && pView.RelativeEnd != null )
            {
                var fTargetObjPos;
                var iTargetSeg = 0;
                if( pView.Segments )
                {
                   while( iTargetSeg < pView.Segments.length && pView.Segments[iTargetSeg].RelativeStart <= fTime )
                   {
                       iTargetSeg++;
                   }
                   iTargetSeg--;
                   var pTargetSeg = pView.Segments[iTargetSeg];
                   fTargetObjPos = pTargetSeg.Offset + fTime - pTargetSeg.RelativeStart; 
                }
                else
                {
                   // our target with respect to the archival video
                   fTargetObjPos = fTime - pView.RelativeStart;    
                }
                
                var fStreamLength = pView.RelativeEnd - pView.RelativeStart;
            
                // we disable the tab if it has relative time parameters and the current time is outside of the
                // relative times - we floor the start so that at the beginning of a session any minor 
                // misalignments between streams are ignores
                var shouldDisable = (fTargetObjPos < 0 || fTargetObjPos > fStreamLength);
                m_pTabControl.SetViewDisabled( pView, shouldDisable );
            }
        }
    }
    
    // process a status event
    this.UpdateStatus = function( pEvent, bUserInitiated )
    {
        m_pLastStatus = pEvent;
        
        if( !m_arrViews )
        {
            return;
        }

        // update the enabled status for all of our views
        this.EnableDisableViews( pEvent.Time );
 
        // send this status update to the current player
        if( m_pSelectedView )
        {
            m_arrPlayers[m_pSelectedView.Type].UpdateStatus( pEvent, bUserInitiated );
        }
    }
    
    this.OnResize = function OnResize(controlHeight, controlWidth)
    {
        // calculate the amount of height we have for content and resize our content div
        var contentTop = m_elContent.offsetTop;
        m_dContentHeightAvailable = controlHeight - contentTop - g_dTabViewerContentPadding * 2;
              
        // keep track of the width we have available - adjust width by content padding
        m_dContentWidthAvailable = controlWidth - (g_dTabViewerContentPadding * 2);
        
        // resize the content control
        ResizeContent();
        
        // Spacing required to vertically center the object material
        var contentPaddingTop = Math.floor((m_dContentHeightAvailable - m_dContentHeight) / 2);
        m_elContent.style.paddingTop = contentPaddingTop + "px";
        
        m_elContent.style.height = m_dContentHeightAvailable - contentPaddingTop + (g_dTabViewerContentPadding * 2) + "px";
        
        // resize our outer div
        m_el.style.height = m_dContentHeightAvailable + (g_dTabViewerContentPadding * 2) + contentTop + "px";
    }
    
    // figure out how large our content control should be and call its resize function
    function ResizeContent()
    {
        var aspect = null;
        var bHavePlayer = false;
        if( m_pSelectedView && m_arrPlayers[m_pSelectedView.Type] )
        {
            aspect = m_arrPlayers[m_pSelectedView.Type].AspectRatio;
            bHavePlayer = true;
        }
        else
        {
            aspect = g_dImageAspect;
        }
        
        // if our player isn't bound by aspect ratio use all avialable space
        if( !aspect && bHavePlayer )
        {
            m_arrPlayers[m_pSelectedView.Type].OnResize( m_dContentWidthAvailable, m_dContentHeightAvailable );
            return;
        }
        
        // determine the actual width and height we will use
        var desiredHeight = m_dContentWidthAvailable / aspect;
        
        // figure out whether to use full height and adjust width or the full width with adjusted hight
        if( desiredHeight > m_dContentHeightAvailable )
        {
            m_dContentWidth = Math.floor(m_dContentHeightAvailable * aspect);
            m_dContentHeight = m_dContentHeightAvailable;
        }
        else
        {
            m_dContentWidth = m_dContentWidthAvailable;
            m_dContentHeight = Math.floor(m_dContentWidthAvailable / aspect);
        }
        
        if( bHavePlayer )
        {
            m_arrPlayers[m_pSelectedView.Type].SetSize( m_dContentWidth, m_dContentHeight );
        }
    }
    
    this.GetContentWidth = function()
    {
        return m_dContentWidth;
    }        
    
    this.SetVisible = function(bVisible)
    {
        SetVisible(m_el, bVisible);
    }
}



// the image viewer control - displays "image" event targets such as PowerPoint slides
function ImageViewer(el)
{
    var m_el = el;
    
    var m_pImage = CreateChildElement(m_el, "img", "imageViewerImage");    
    var m_pCurImageUrl = null;
    var m_dImageWidth;
    var m_dImageHeight;
    var m_pLastEvent = null;
    var m_arrTimestamps = null;

    // this is needed by TabViewer for layout
    this.AspectRatio = g_dImageAspect;
    
    this.Initialize = function(pStream)
    {
        m_arrTimestamps = pStream.Timestamps;
    }
    
    this.SetVisible = function(bVisible)
    {
        SetVisible(m_el, bVisible);
    }
    
    this.UpdateStatus = function(pEvent)
    {
        m_pLastEvent = pEvent;
        
        // if SetSize hasn't yet been called then return
        if( !m_dImageHeight || !m_dImageWidth )
            return;
            
        var iItem = GetCurrentItem( m_arrTimestamps, pEvent.Time );
        var pImage = m_arrTimestamps[iItem];
				
				// modified [20081117 by wmc], force slide name to lowercase
        var url = pImage.EventTargetPublicID + "_ET/images/slide" + pImage.SequenceNumber + ".jpg";        
        /*
        var url = pImage.EventTargetPublicID + "_ET/images/Slide" + pImage.SequenceNumber + ".JPG";        
				*/
        if( url != m_pCurImageUrl )
        {
            m_pCurImageUrl = url;
            m_pImage.src = url;
        }
    }
    
    this.SetSize = function(contentWidth, contentHeight)
    {
        m_dImageHeight = contentHeight;
        m_dImageWidth = Math.floor(contentWidth);
        
        m_el.style.width = contentWidth + "px";
        m_pImage.style.width = m_dImageWidth + "px";
    }
}


// control for rendering tab bar and switching between views
function TabControl(el, selectViewCallback, useLargeTabs)
{
    var m_tabsEl = el;
    var m_selectViewCallback = selectViewCallback;
    
    var m_arrViews = null;
    var m_pSelectedView = null;
    
    var m_bUseLargeTabs = useLargeTabs;

    // set our list of views
    this.SetViews = function SetViews(views)
    {
        // create tabs for each of the views
        m_arrViews = views;
        for( var index in m_arrViews )
        {
            var pView = m_arrViews[index];
            var tabClass = GetTabClass(false, pView.Disabled);
            pView.Div = CreateChildElement( m_tabsEl, "div",  tabClass);
            pView.Div.innerHTML = pView.Title;
            pView.Div.onselectstart = function () { return false; };
          
            function callback( iIndex )
            {
                // if the view is already selected or disabled then return
                var pSelectView = m_arrViews[iIndex];
                if( pSelectView == m_pSelectedView || pSelectView.Disabled )
                {
                    return;
                }
                SelectView( m_arrViews[iIndex] );
            }
            
            pView.Div.onclick = Clicker( pView.Div, callback, index );
        }
        
        // start off by rendering the first view
        this.SetFirstEnabledView()
    }
    
    this.SelectFirstViewWithData = function(field, value)
    {
        for( var index in m_arrViews )
        {
            var pView = m_arrViews[index];  
            if(pView[field] == value)
            {
                SelectView( pView );
                return;
            }
        }
    }
    
    // called when a tab is clicked
    function SelectView(pView)
    {
        // if we aren't changing anything then return
        if( pView == m_pSelectedView )
            return;
            
        // call callback if present 
        if( m_selectViewCallback )
            m_selectViewCallback( pView );
        
        // unselect the currently selected tab
        if( m_pSelectedView )
        {
            m_pSelectedView.Div.className = GetTabClass(false, m_pSelectedView.Disabled);
        }
        
        // update the new view and change its tab
        m_pSelectedView = pView;
        if( m_pSelectedView )
        {
            m_pSelectedView.Div.className = GetTabClass(true, false);
        }
    }
    
    // go through all the views and select the first that is enabled
    this.SetFirstEnabledView = function()
    {
        for( var p in m_arrViews )
        {
            var newView = m_arrViews[p];
            if( !newView.Disabled )
            {
                SelectView( newView );
                return;
            }
        }
        
        // if there are no enabled views, select view with null
        SelectView( null );
    }
    
    // call to enable/disable views
    this.SetViewDisabled = function SetViewDisabled( view, bDisabled )
    {
        if( bDisabled )
        {
            // if we are already disabled do nothing
            if( view.Disabled )
            {
                return;
            }
            
            if( view.Div )
            {
                view.Div.className = GetTabClass(false, true);
            }
            view.Disabled = true;
            
            // if we have disabled the selected view, then select the first non-disabled view
            if( view == m_pSelectedView )
            {
                this.SetFirstEnabledView();
            }        
        }
        else
        {
            // if we are disabled change the tab
            if( view.Disabled )
            {
                view.Div.className = GetTabClass(false, false);
                view.Disabled = false;
            }
            
            // if we don't have a selected view, select this one
            if( !m_pSelectedView )
            {
                this.SetFirstEnabledView();
            }
        }
    }
    
    function GetTabClass(isSelected, isDisabled)
    {
        var strTabClass = isSelected ? "tabDivSelected" : "tabDiv";
        strTabClass = isDisabled ? "tabDivDisabled" : strTabClass;

        strTabClass += " ";

        if(isSelected)
        {
            strTabClass += m_bUseLargeTabs ? "tabImageSelected_large" : "tabImageSelected_small";
        }
        else
        {
            strTabClass += m_bUseLargeTabs ? "tabImage_large" : "tabImage_small";
        }
        
        return strTabClass;
    }
}


