
// Copyright (c) 2003 Sonic Foundry, Inc. and Sonic Foundry 
// Media Systems, Inc. Neither this code nor any portion 
// thereof may be reproduced, altered, or otherwise changed, 
// distributed or copied, without the express written 
// permission of Sonic Foundry.  
// All rights reserved.

// BEGINFILE constants.js --------------------------------------------------------------------------->

var PlayState =
{
	Undefined:		0,
    Stopped:        1,
    Paused:         2,
    Playing:        3,
    ScanForward:    4,
    ScanReverse:    5,
    Buffering:		6,
    Waiting:		7,
    MediaEnded:		8,
    Transitioning:	9,
    Ready:			10,
    Opening:		11
}

var OpenState =
{
	Undefined:					0,
	PlaylistChanging:			1,
	PlaylistLocating:			2,
	PlaylistConnecting:			3,
	PlaylistLoading:			4,
	PlaylistOpening:			5,
	PlaylistOpenNoMedia:		6,
	PlaylistChanged:			7,
	MediaChanging:				8,
	MediaLocating:				9,
	MediaConnecting:			10,
	MediaLoading:				11,
	MediaOpening:				12,
	MediaOpen:					13,
	BeginCodecAcquisition:		14,
	EndCodecAcquisition:		15,
	BeginLicenseAcquisition:	16,
	EndLicenseAcquisition:		17,
	BeginIndividualization:		18,
	EndIndivididualization:		19,
	MediaWaiting:				20,
	OpeningUnknownURL:			21
}
	


function GetPlayStateName(state)
{
	switch (state)
	{
		case PlayState.Undefined:
			return "Undefined";
		case PlayState.Stopped:
			return "Stopped";
		case PlayState.Paused:
			return "Paused";
		case PlayState.Playing:
			return "Playing";
		case PlayState.ScanForward:
			return "ScanForward";
		case PlayState.ScanReverse:
			return "ScanReverse";
		case PlayState.Buffering:
			return "Buffering";
		case PlayState.Waiting:
			return "Waiting";
		case PlayState.MediaEnded:
			return "MediaEnded";
		case PlayState.Transitioning:
			return "Transitioning";
		case PlayState.Ready:
			return "Ready";
		case PlayState.Opening:
			return "Opening";
		default:
			return "Uknown State Type";
	}
}

// ENDFILE constants.js ----------------------------------------------------------------------------->

// BEGINFILE ScriptParse.js ------------------------------------------------------------------------->

function ScriptParser()
{
	this.m_debugLevel = SfDebug.Verbose;
//	this.m_debugLevel = SfDebug.Information;

	this.ParseScriptFromStream = function(sType, sParam)
	{
		this.Debug("ParseScriptFromStream called: ScriptType: " + sType + ", ScriptParam: " + sParam);
		switch(sType)
		{
			case "MSLiveEvent":
//				alert('this eventtype MSLiveEvent is not supported');
//				break;
			case "MSL":
				eval("this." + sParam + "");
				break;
		}
	}

	// this is the one which notifies to all interested Areas
	this.NotifyScriptEvent = function(oArgs)
	{
		this.Debug("NotifyScriptCommand called");
		MainHelper.EventScript.Post(oArgs);
	}
	
	this.Debug = function(str)
	{
		SfDebug.DPF(this.m_debugLevel, "ScriptParser: " + str);
	}
	
	
	// new event stuff below this------------------------------------------------------------------------
	// HE('EventType', Param1, Param2...);
	// this function is directly called by the mac player
	this.HE = function()
	{
		this.Debug("HE called");
		if (arguments.length < 1)
		{
			SfDebug.DPF(SfDebug.ErrMsgCritical, "The event must be of the form " + 
				"HE('EventType', [args....])");
			return;
		}
		
		var command = arguments[0];
		switch (command)
		{
			case "S":
				if (arguments.length < 2)
				{
					SfDebug.DPF(SfDebug.ErrMsgCritical, "ShowSlide wrong arguments: " + arguments);	
					return;
				}
				var slideNumber = Number(arguments[1]);
				if (MainHelper.MaxSlideTimings < slideNumber)
				{
					MainHelper.KeepAddingToSlideTimings(slideNumber);
					MainHelper.DynamicAdd = true;
				}
				else
				{
					MainHelper.DynamicAdd = false;
				}
				
				MainHelper.PresentationEnded = false;
				var args = MainHelper.CreateShowSlideEventArgs(slideNumber);
				MainHelper.CurrentSlideNumber = slideNumber;
				this.NotifyScriptEvent(args);
				break;
			case "E":
				var args = new Object();
				args.Command = SfScriptCommandType.EndPresentation;
				if (MainHelper.Presentation.DoReporting == true)
				{
					this.ReportEndPresentationEvent();
				}
				this.NotifyScriptEvent(args);
				break;
		}
	} 
	
	this.ReportEndPresentationEvent = function()
	{
		this.Debug("ReportEndPresentationEvent");
		var imageSource = 
			Util.GetDocumentBase() + 
			"/Reporting/ReportEndPresentationEvent.aspx?" + 
			"&" + SfRequestVariables.PresentationExperienceID + "=" + MainHelper.Presentation.PresentationExperienceID +
			"&" + SfRequestVariables.MediaTicketId + "=" + MainHelper.Presentation.MediaTicketId +
			"&" + SfRequestVariables.EventID + "=" + MainHelper.Presentation.EventID;
		
		var frameLoader = new FrameLoader(imageSource);
		frameLoader.Load();
	}

}

// ENDFILE ScriptParse.js --------------------------------------------------------------------------->


// BEGINFILE PlayerArea.js -------------------------------------------------------------------------->

PlayerArea.prototype = new AreaBase();
function PlayerArea(container, containingWindow, ID)
{
	this.m_debugLevel = SfDebug.Verbose;
	this.PlayerType = "Unknown"; // should override in derived classs
	this.ScriptParser = new ScriptParser();
	this.AttemptNumber = 0;
	this.StatusFrameLoader = null;
	this.StartTime = -1;
	this.PartitionManager = null;

	this.Debug = function(str)
	{
		SfDebug.DPF(this.m_debugLevel, "PlayerArea: PlayerType = " + this.PlayerType + ": " + str);
	}
	
	this.OnLoad = function()
	{
		this.Debug("OnLoad called");
		// delegate to the other method because
		// we need to override onload for 
		// the playerarea for mac
		this.DoOnLoad();
	}
	
	this.DoOnLoad = function()
	{
		this.Debug("DoOnLoad called");

		this.InitializePartitionManager();
		
		this.WaitOnMediaTicketId();
	}
	
	this.InitializePartitionManager = function()
	{
		var timings = new Array(MainHelper.Presentation.SlideTimings.length);
		for (var i=0; i<timings.length; ++i)
		{
			timings[i] = MainHelper.Presentation.SlideTimings[i].Time;
		}
		
		this.PartitionManager = new Player_PartitionManager(timings);
	}
	
	this.WaitOnMediaTicketId = function()
	{
		this.Debug("WaitOnMediaTicketId()");
	
		if (MainHelper.Presentation.MediaTicketInitializationDone == false)
		{
			window.setTimeout(this.Container + ".WaitOnMediaTicketId()", 500);
		}
		else
		{
			if (MainHelper.Presentation.MediaTicketId != null)
			{
				MainHelper.Presentation.VideoUrl = MainHelper.Presentation.VideoUrl + "&" + SfRequestVariables.MediaTicketId + "=" + MainHelper.Presentation.MediaTicketId;
			}
			
			this.CheckPresentationStatus();
		}
	}
	
	this.CheckPresentationStatus = function()
	{
		this.Debug("CheckPresentationStatus()");
		var status = MainHelper.Presentation.Status;

		switch (status)
		{
			case PresentationStatus.CaptureInProgress:
			case PresentationStatus.ReplayReady:
				this.StartPlaying();
				return;
			case PresentationStatus.Ended:
				return;
			case PresentationStatus.NotReady:
			case PresentationStatus.CaptureReady:
				this.DoNotReadyStuff();
				return;
			default:
				alert('Unknown Presentation Status');
				return;
		}
		
	}

	this.GetEmbeddedPlayer = function()
	{
		var playerType = MainHelper.PlayerDetect.GetPlayerType();
		switch(playerType)
		{
			case PlayerType.WM64Lite = "WM64Lite":
			case PlayerType.WM64 = "WM64":
			case PlayerType.WM7 = "WM7":
			case PlayerType.Port25 = "Port25":
			case PlayerType.Unknown = "Unknown":
				return SfDOM.FindElementFromID(document, "EmbeddedPlayer");
			default:
				alert('Unknown PlayerType');
		}
	}
	
	this.DoNotReadyStuff = function()
	{
		this.Debug("DoNotReady()");
		var image = SfDOM.FindElementFromID(document, "PlayerPresentationNotStarted");
		if (image)
		{
			image.style.display = '';
		}
		else
		{
			this.Debug("!!NotStartedImage not found");
		}

		this.HidePlayerDivWhenNotReady();

		this.StatusFrameLoader = new FrameLoader(this.GetFrameSource());
		this.KeepChecking();
	}

	this.GetFrameSource = function()
	{
		if (MainHelper.Presentation.IsStandAlone == true)
		{
			return Util.GetDocumentBase() +
				"/CurrentStatus.html";
		}
		else
		{
			return Util.GetDocumentBase() + 
				"/StatusChange/StatusChangeMonitor.aspx?" + SfRequestVariables.PresentationID + "=" + MainHelper.Presentation.PresentationID;
		}	
	}

	this.KeepChecking = function()
	{
		++this.AttemptNumber;
		this.Debug("KeepChecking called , attempt: " + this.AttemptNumber);
		this.StatusFrameLoader.Load();
	}
		
	this.NotReady = function(checkInterval)
	{
		this.Debug("NotReady called: interval: " + checkInterval);
		window.setTimeout(this.Container + ".KeepChecking()", checkInterval);
	}
	
	this.Ready = function(currentSlideNumber)
	{
		this.Debug("Ready()");

		//!! port 25 hack
		if (MainHelper.PlayerDetect.GetPlayerType() == PlayerType.Port25)
		{
			window.location.reload();
			return;
		}

		var image = SfDOM.FindElementFromID(document, "PlayerPresentationNotStarted");
		if (image)
		{
			image.style.display = 'none';
		}
		else
		{
			this.Debug("!!NotStartedImage not found");
		}
		
		this.ShowPlayerDivWhenReady();

		this.AddSlideTimingsIfRequired(currentSlideNumber);

		MainHelper.Presentation.Status = PresentationStatus.CaptureInProgress;
		MainHelper.EventDataAvailable.Post(new SfEventArgs());

		this.StartPlaying();
	}
	
	this.ShowPlayerDivWhenReady = function()
	{
		alert('ShowPlayerDivWhenReady() not implemented');
	}
	
	this.HidePlayerDivWhenNotReady = function()
	{
		alert('HidePlayerDivWhenNotReady() not implemented');
	}
	
	this.AddSlideTimingsIfRequired = function(currentSlideNumber)
	{
		this.Debug("AddSlideTimingsIfRequired()");
		
		if (currentSlideNumber == -1)
		{
			this.Debug("No need to add");
			return;
		}
		
		MainHelper.KeepAddingToSlideTimings(currentSlideNumber);
	
	}

	this.StartPlaying = function()
	{
		this.Debug("StartPlaying called");

		this.SetupPlayer();
		
		if (MainHelper.Presentation.DoReporting == true)
		{
			this.ReportViewerPageOpened();
		}
	}
	
	this.ReportViewerPageOpened = function()
	{
		this.Debug("ReportViewerPageOpened");
		var imageSource = 
			Util.GetDocumentBase() + 
			"/Reporting/ReportViewerPageOpened.aspx?" + 
			"&" + SfRequestVariables.PresentationExperienceID + "=" + MainHelper.Presentation.PresentationExperienceID +
			"&" + SfRequestVariables.EventID + "=" + MainHelper.Presentation.EventID +
			"&" + SfRequestVariables.MediaTicketId + "=" + MainHelper.Presentation.MediaTicketId +
			"&" + SfRequestVariables.IsLive + "=" + this.GetIsLiveString();

		var frameLoader = new FrameLoader(imageSource);
		frameLoader.Load();
	}
	
	this.GetIsLiveString = function()
	{
		if (MainHelper.Presentation.Status == PresentationStatus.CaptureInProgress)
		{
			return "true";
		}
		else
		{
			return "false";
		}
	}
	
	this.ResizeWindow = function()
	{
		this.Debug("ResizeWindow called: ViewerWidth: " + this.ViewerWidth + ", ViewerHeight: " + this.ViewerHeight);
		if (this.ViewerWidth == -1 || this.ViewerHeight == -1)
		{
			this.Debug("no resize needed");
			return;
		}
		var extraWidth = MainHelper.GetFrameExtraWidth();
		var extraHeight = MainHelper.GetFrameExtraHeight();
		window.resizeTo(this.ViewerWidth + extraWidth, this.ViewerHeight + extraHeight);		
	}
	
	this.CalculateSlideNumberToShow = function(time)
	{
		if (time < 0)
		{
			return 0;
		}
		return this.PartitionManager.GetSlideNumberToShow(time);
	}
}

// ENDFILE PlayerArea.js ---------------------------------------------------------------------------->
Player_Partition = function(left, right)
{
	this.MinIndex = left;
	this.MaxIndex = right;
	this.Left = null;
	this.Right = null;
}
Player_Partition.prototype = 
{
	GetCount : function()
	{
		return this.MaxIndex - this.MinIndex + 1;
	},
	
	CreateSubPartitions : function()
	{
		var middle = Math.floor( (this.MinIndex + this.MaxIndex) / 2 );
		this.Left = new Player_Partition(this.MinIndex, middle);
		this.Right = new Player_Partition(middle+1, this.MaxIndex);
		return {Left:this.Left, Right:this.Right};
	}
}
Player_PartitionManager = function(timings)
{
	this._timings = timings;
	this._timeCode = null;
}
Player_PartitionManager.prototype = 
{
	GetSlideNumberToShow : function(timeCode)
	{
		if (this._timings.length == 0)
		{
			return 0;
		}
		
		this._timeCode = timeCode;
	
		return this._FindInPartition(new Player_Partition(0, this._timings.length-1));	
	},
	
	_FindInPartition : function(partition)
	{
		var count = partition.GetCount();
		if (count == 1)
		{
			return this._FindIn1Partition(partition);
		}
		else if (count == 2)
		{
			return this._FindIn2Partition(partition);
		}
		
		partition.CreateSubPartitions();

		if (this._timeCode < this._timings[partition.Left.MinIndex])
		{
			return partition.Left.MinIndex;
		}
		else if (this._IsPresentInPartition(partition.Left) == true)
		{
			return this._FindInPartition(partition.Left);			
		}
		else if (this._timeCode < this._timings[partition.Right.MinIndex])
		{
			return partition.Right.MinIndex;
		}
		else if (this._IsPresentInPartition(partition.Right) == true)
		{
			return this._FindInPartition(partition.Right);
		}
		else
		{
			return partition.Right.MaxIndex+1;
		}
	},
	
	_FindIn1Partition : function(partition)
	{
		var partitionTime = this._timings[partition.MinIndex];
		
		if (this._timeCode < partitionTime)
		{
			return partition.MinIndex;
		}
		else
		{
			return partition.MinIndex+1;			
		}
	},
	
	_FindIn2Partition : function(partition)
	{
		var time1 = this._timings[partition.MinIndex];
		var time2 = this._timings[partition.MaxIndex]

		if (this._timeCode < time1)
		{
			return partition.MinIndex;
		}
		else if (this._timeCode >= time1 && this._timeCode < time2)
		{
			return partition.MinIndex+1;
		}
		else
		{
			return partition.MaxIndex+1;
		}
	},
	
	_IsPresentInPartition : function(partition)
	{
		return (this._timeCode >= this._timings[partition.MinIndex] && this._timeCode <= this._timings[partition.MaxIndex]);
	}
}


