/// <reference path="OwcViewer.js" />
/// <reference path="OwcDataBound.js" />
if (typeof(JScript) == "undefined")
	throw DHTML.newError(0, "JavaScript OOP API is not included.  Add JScriptCore.js to your file");

if (typeof(Olive) == "undefined" || !Olive.Controls)
	throw DHTML.newError(0, "Olive Web SDK core classes are not included.  Add OwcControl.js to your file");

// -------------------------- Constants -------------------------
Olive.Controls.controlTypeNames.FlashViewer = "flashviewer";

// FlashViewer attributes
Olive.Controls.attributes.FlashContentOptions = Olive.Controls.xmlns + "FlashContentOptions";
Olive.Controls.attributes.BgColor = Olive.Controls.xmlns + "BgColor";
Olive.Controls.attributes.AllowTransparentOnMac = Olive.Controls.xmlns + "allow-transparent-on-mac";
// attribute for showing first page of search results; possible values: "with-hits"(default) or "on-entity"
Olive.Controls.attributes.FirstPage = Olive.Controls.xmlns + "first-page";

var OwcFlashViewer_WithHits = "with-hits";
var OwcFlashViewer_OnEntity = "on-entity";

var OwcFlashParam_OpenTOCAtStart = "OpenTOCAtStart";
var OwcFlashParam_OnePageMode = "OnePageMode";

// Flash object actions.

var gRefFlashReader = null;

/*=============================================================================
 * Class   : Olive.Controls.FlashViewer
 * Summary : Display page images in Flash viewer with hits highlights, paging animation, text view, etc.
=============================================================================*/
if (!Olive.Controls.FlashViewer)
{
	Olive.Controls.FlashViewer = function OwcFlashViewer()
	{
	}; // Olive.Controls.FlashViewer() constructor

    Olive.Controls.FlashViewer.MouseMode = 
    {
		Text : "textload",
		SmartZoom : "smartzoommode",
		SimpleZoom : "simplezoommode",
		NoZoom : "nozoommode" // not in use
	}

	Olive.Controls.FlashViewer.ApplyPrototype = function OwcFlashViewer_ApplyPrototype(rObject)
	{
		// OwcFlashViewer class implementation
		Olive.Controls.IDataBound.ImplementInterface( rObject );

        JScript.Type.ReplaceMethod(rObject, "bindHtmlElement", OwcFlashViewer_bindHtmlElement);
        JScript.Type.OverrideMethod(rObject, "initControl", OwcFlashViewer_initControl);
		JScript.Type.OverrideMethod(rObject, "parseControlHtmlAttr", OwcFlashViewer_parseControlHtml);
		JScript.Type.OverrideMethod(rObject, "contentBuildControlParams", OwcFlashReader_contentBuildControlParams);
		JScript.Type.OverrideMethod(rObject, "contentLoad", OwcFlashReader_contentLoad);
		JScript.Type.OverrideMethod(rObject, "processResponse", OwcFlashReader_processResponse);
		JScript.Type.ReplaceMethod(rObject, "gotoPageInternal", OwcFlashViewer_gotoPageInternal); // Override from base class
		JScript.Type.ReplaceMethod(rObject, "gotoPageWithHighlighting", OwcFlashViewer_gotoPageWithHighlighting);
		JScript.Type.ReplaceMethod(rObject, "gotoPageWithHighlightingIntenal", OwcFlashViewer_gotoPageWithHighlightingIntenal);
		JScript.Type.ReplaceMethod(rObject, "cmdChangeModeDoublePage", OwcFlashViewer_cmdChangeModeDoublePage);
		JScript.Type.ReplaceMethod(rObject, "cmdChangeModeFlipAnimationEffect", OwcFlashViewer_cmdChangeModeFlipAnimationEffect);
		JScript.Type.ReplaceMethod(rObject, "cmdChangeModeHighlightTitles", OwcFlashViewer_cmdChangeModeHighlightTitles);
		JScript.Type.ReplaceMethod(rObject, "cmdChangeModeHighlightEntitiesOnMouseOver", OwcFlashViewer_cmdChangeModeHighlightEntitiesOnMouseOver);
		JScript.Type.ReplaceMethod(rObject, "cmdChangeModeMouseBehavior", OwcFlashViewer_cmdChangeModeMouseBehavior);
		JScript.Type.ReplaceMethod(rObject, "setRotationInternal", OwcFlashViewer_setRotationInternal);
		JScript.Type.ReplaceMethod(rObject, "internalSetZoomFactor", OwcFlashViewer_internalSetZoomFactor);
        JScript.Type.ReplaceMethod(rObject, "zoomFitWidth", OwcFlashViewer_zoomFitWidth);
        JScript.Type.ReplaceMethod(rObject, "zoomFitHeight", OwcFlashViewer_zoomFitHeight);
        JScript.Type.ReplaceMethod(rObject, "zoomFitWindow", OwcFlashViewer_zoomFitWindow);
        JScript.Type.ReplaceMethod(rObject, "setPageLabels", OwcFlashViewer_setPageLabels); // internal set pageLabels data

        // Navigation
        JScript.Type.ReplaceMethod(rObject, "_onFlipAreaOrPageButtonClickedDefault", OwcFlashViewer_onFlipAreaOrPageButtonClicked);		

        //Hit Navigation
		JScript.Type.DeclareMethod(rObject, "viewerGotoPrevHitPage", OwcFlashViewer_viewerGotoPrevHitPage);
		JScript.Type.DeclareMethod(rObject, "viewerGotoNextHitPage", OwcFlashViewer_viewerGotoNextHitPage);
		JScript.Type.DeclareMethod(rObject, "viewerGotoLastHitPage", OwcFlashViewer_viewerGotoLastHitPage);
		JScript.Type.DeclareMethod(rObject, "viewerGotoFirstHitPage", OwcFlashViewer_viewerGotoFirstHitPage);
		JScript.Type.DeclareMethod(rObject, "clearSearchHits", OwcFlashViewer_clearSearchHits);
		JScript.Type.DeclareMethod(rObject, "loadSearchHits", OwcFlashViewer_loadSearchHits);
		JScript.Type.DeclareMethod(rObject, "loadSearchHitsForDocument", OwcFlashViewer_loadSearchHitsForDocument);
		JScript.Type.DeclareMethod(rObject, "loadSearchHitsForEntity", OwcFlashViewer_loadSearchHitsForEntity);
		
        JScript.Type.DeclareMethod(rObject, "setTextMouseMode", OwcFlashViewer_setTextMouseMode);
        JScript.Type.DeclareMethod(rObject, "setSmartZoomMouseMode", OwcFlashViewer_setSmartZoomMouseMode);
        JScript.Type.DeclareMethod(rObject, "setSimpleZoomMouseMode", OwcFlashViewer_setSimpleZoomMouseMode);
        JScript.Type.DeclareMethod(rObject, "setMouseMode", OwcFlashViewer_setMouseMode);
        JScript.Type.DeclareMethod(rObject, "getMouseMode", OwcFlashViewer_getMouseMode);
        JScript.Type.DeclareMethod(rObject, "queryCmdUiState_MouseMode", OwcFlashViewer_queryCmdUiState_MouseMode);
        
        JScript.Type.DeclareMethod(rObject, "downloadPDF", OwcFlashViewer_downloadPDF);
        JScript.Type.DeclareMethod(rObject, "print", OwcFlashViewer_print);
        JScript.Type.DeclareMethod(rObject, "about", OwcFlashViewer_about);
        JScript.Type.DeclareMethod(rObject, "saveForOffline", OwcFlashViewer_saveForOffline);
        JScript.Type.DeclareMethod(rObject, "toggleTOC", OwcFlashViewer_toggleTOC);
        JScript.Type.DeclareMethod(rObject, "sendCommandToPlugIn", OwcFlashViewer_sendCommandToPlugIn);

		JScript.Type.DeclareMethod(rObject, "displayDocument", OwcFlashViewer_displayDocument);
		JScript.Type.DeclareMethod(rObject, "readSearchQuery", OwcFlashViewer_readSearchQuery);
		JScript.Type.ReplaceMethod(rObject, "sendRequestRaw", OwcFlashViewer_sendRequestRaw);//overridden
		JScript.Type.DeclareMethod(rObject, "processCustomFlashEvent", OwcFlashReader_processCustomFlashEvent);//pure virtual

		JScript.Type.DeclareMethod(rObject, "getFlashObjRef", OwcFlashReader_getFlashObjRef);
		JScript.Type.DeclareMethod(rObject, "flashContainerHide", OwcFlashReader_flashContainerHide);
		JScript.Type.DeclareMethod(rObject, "flashContainerShow", OwcFlashReader_flashContainerShow);
		JScript.Type.DeclareMethod(rObject, "closeTOC", OwcFlashReader_closeTOC);

		// Helper functions
		JScript.Type.DeclareMethod(rObject, "generateHTMLContent", OwcFlashReader_generateHTMLContent);
		JScript.Type.DeclareMethod(rObject, "HighlightSearchResults", OwcFlashReader_HighlightSearchResults);
		JScript.Type.DeclareMethod(rObject, "HighlightSearchResults_AfterLoad", OwcFlashReader_HighlightSearchResults_AfterLoad);
		JScript.Type.DeclareMethod(rObject, "passToFlashObj", OwcFlashReader_passToFlashObj);
		JScript.Type.DeclareMethod(rObject, "sendCommandToFlashObj", OwcFlashViewer_sendCommandToFlashObj);
		JScript.Type.DeclareMethod(rObject, "sendCommandsToFlashObj", OwcFlashViewer_sendCommandsToFlashObj);
		JScript.Type.DeclareMethod(rObject, "parseQueryString", OwcFlashReader_parseQueryString);
		JScript.Type.DeclareMethod(rObject, "parseParams", OwcFlashReader_parseParams);
		JScript.Type.DeclareMethod(rObject, "isLiveConnectAvailable", OwcFlashReader_isLiveConnectAvailable);
		JScript.Type.DeclareMethod(rObject, "getFlashEventDataString", OwcFlashReader_getFlashEventDataString);
		JScript.Type.DeclareMethod(rObject, "synchronizeData", OwcFlashViewer_synchronizeData);
		JScript.Type.DeclareMethod(rObject, "syncField", OwcFlashViewer_syncField);
		JScript.Type.DeclareMethod(rObject, "dispatchFlashEvent", OwcFlashReader_DispatchFlashEvent);
		JScript.Type.DeclareMethod(rObject, "attachMouseWheelEvent", OwcFlashViewer_attachMouseWheelEvent);

		// Properties
		//rObject.m_bDisableContentAutoLoad = true;//??
        JScript.Type.DeclareField(rObject, "m_sMouseMode", Olive.Controls.FlashViewer.MouseMode.SmartZoom); //Internal
		JScript.Type.DeclareField(rObject, "bgColor", "#808080");
		JScript.Type.DeclareField(rObject, "m_bAllowTransparentOnMac", false); // allow WMode="transparent" on Mac
		JScript.Type.DeclareField(rObject, "m_sWModeForTransparency", "transparent"); // change to "opaque" on Mac if(!this.m_bAllowTransparentOnMac)
		JScript.Type.DeclareField(rObject, "m_sWMode", "opaque");
		JScript.Type.DeclareField(rObject, "m_oHtmlParams", {}); //from custom attributes
		JScript.Type.DeclareField(rObject, "m_oAppArgParams", {}); //passed as argument to displayDocument()
		JScript.Type.DeclareField(rObject, "objChunksDataStorage", new Object());

		JScript.Type.DeclareField(rObject, "flashObjRef", null);//Reference to Flash Application object
		//	Flash object ID, must be unique, in case there are many objects in the container.
		//	But, for a while this value is predefined, and we supposed, that in one 
		//	div, there is only one flash object.
		
		//!QS, which has been passed to Flash in URL or like param!
		//-QS to Flash has been built from the next params:
		JScript.Type.DeclareField(rObject, "m_sQueryStr", ""); //additional params, like Zoom, ZoomOn, etc, delimited by  '|' ??);
		JScript.Type.DeclareField(rObject, "m_sSearchStr", null); //search string, in notation(~word)
		JScript.Type.DeclareField(rObject, "m_sCollection", null);
		JScript.Type.DeclareField(rObject, "m_sLanguage", null);	
		JScript.Type.DeclareField(rObject, "m_sPrimId", null);
		JScript.Type.DeclareField(rObject, "m_nPageNo", null);
		JScript.Type.DeclareField(rObject, "m_sPageLabel", null);
		JScript.Type.DeclareField(rObject, "m_bShown", true);
		
		JScript.Type.DeclareField(rObject, "urlFlashReader", "");
		JScript.Type.DeclareField(rObject, "urlLoaderSwfFile", "");
		JScript.Type.DeclareField(rObject, "urlSkinSwfFile", "");
		JScript.Type.DeclareField(rObject, "urlSplashSwfFile", "");
		JScript.Type.DeclareField(rObject, "urlEmptySwfFile", "");
		JScript.Type.DeclareField(rObject, "bHtmlPasteFlash", true);
		JScript.Type.DeclareField(rObject, "sFirstPage", OwcFlashViewer_WithHits); //default, show search result page on the page with a first hit

		// constants (TODO: remove some of these)
		JScript.Type.DeclareField(rObject, "OwcBaseDir", "");//"/Tests/WebComponents/v2.0/Components/");//"/Olive/WebComponents/");
		JScript.Type.DeclareField(rObject, "UrlParam_RequestType", "RequestType");
		JScript.Type.DeclareField(rObject, "UrlParam_PrimitiveBox", "PrimitiveBox");
		JScript.Type.DeclareField(rObject, "UrlParam_LoadFlash", "LoadFlash");
		JScript.Type.DeclareField(rObject, "UrlParam_DPBaseUrl", "DPBaseUrl"); 
		JScript.Type.DeclareField(rObject, "UrlParam_DPType", "DataProviderType");
		JScript.Type.DeclareField(rObject, "UrlParam_PrimId", "PrimId");
		JScript.Type.DeclareField(rObject, "UrlParam_Path", "Path");
		JScript.Type.DeclareField(rObject, "UrlParam_PageNo", "PageNo");
		JScript.Type.DeclareField(rObject, "UrlParam_Label", "PageLabel");
//		JScript.Type.DeclareField(rObject, "FlashSourceUrl", rObject.OwcBaseDir + "OlvFlashReaderApp.swf");
		JScript.Type.DeclareField(rObject, "EP_APPLICATION_NAME", "EP");
		if( typeof getEP_AppName == "function" && getEP_AppName() )
			rObject.EP_APPLICATION_NAME = getEP_AppName();
		JScript.Type.DeclareField(rObject, "FlashDefaultObjId", null);//default value of <object id> "OlvFlashReaderApp");
		JScript.Type.DeclareField(rObject, "EP_FlashUIDVarName", "ResponseUID");
		JScript.Type.DeclareField(rObject, "EP_FlashDataVarName", "ResponseData");

		//events
		rObject.registerOwcEventsClass2("flashEventReceived", "onFlashEventReceived", true);
		rObject.registerOwcEventsClass2("flashGotoPage", "onFlashGotoPage", true); // fires from gotoPageInternal
		rObject.registerOwcEventsClass2("print", "onPrint", true);
		rObject.registerOwcEventsClass2("saveForOfflineStarted", "onSaveForOfflineStarted",true); 
		rObject.registerOwcEventsClass2("saveForOfflineEnded", "onSaveForOfflineEnded",true); 
		rObject.registerOwcEventsClass2("saveForOfflineProgress", "onSaveForOfflineProgress",true); 
		rObject.registerOwcEventsClass2("toggleFrame", "onToggleFrame",true);
		rObject.registerOwcEventsClass2("mouseModeChanged", "onMouseModeChanged",true); // sMouseMode
		rObject.registerOwcEventsClass2("oldFlashPlayerVersion", "onOldFlashPlayerVersion",true); //sCurrentVersion, sExpectedVersion, sDownloadURL
		rObject.registerOwcEventsClass2("errorStatusReceived", "onErrorStatusReceived", true);


		Olive.CmdTarget.RegisterCommand(rObject, "setTextMouseMode", "setTextMouseMode", "queryCmdUiState_MouseMode");
		Olive.CmdTarget.RegisterCommand(rObject, "setSmartZoomMouseMode", "setSmartZoomMouseMode", "queryCmdUiState_MouseMode");
		Olive.CmdTarget.RegisterCommand(rObject, "setSimpleZoomMouseMode", "setSimpleZoomMouseMode", "queryCmdUiState_MouseMode");
		Olive.CmdTarget.RegisterCommand(rObject, "downloadPDF", "downloadPDF", null);
		Olive.CmdTarget.RegisterCommand(rObject, "print", "print", null);
		Olive.CmdTarget.RegisterCommand(rObject, "about", "about", null);
		Olive.CmdTarget.RegisterCommand(rObject, "saveForOffline", "saveForOffline", null);
	};
	
	function OwcFlashViewer_receiveErrorFromFlash()
	{
	    // Get Flash control ID.
	    var sSelfID = arguments[0];
	    // Get error message.
	    var sErrorMessage = arguments[1];
	    
	    // Find the Flash control, create and send an error event.
	    var oFlashReaderCtrl = OwcGetControl(sSelfID, true);
		var oEvent = oFlashReaderCtrl.createOwcEventObject("errorStatusReceived");
		oEvent.sErrorMessage = sErrorMessage;
		oFlashReaderCtrl.fireOwcEvent(oEvent);
		Object_Destroy(oEvent);
	}
	
	function OwcFlashViewer_bindHtmlElement(oHtmlElement)
	{
	    // to avoid binding to mouse events in IDataBound on content item clicked:
	    OwcControl_bindHtmlElement.call(this, oHtmlElement);
	    // Alternatives to this solution:
	    // 1) Boolean variable can be used in data bound, bAutoBindToHTMLEvents which will set to false before bindHTMLElement call to base class
	    //      as in case of m_bDisableContentAutoLoad in databound.
	    // 2) Event handler can be defined in IDataBound (now it is used as global) and replace it in controls prototype.

		// Firefox and Safari - Flash mouse wheel does not work with wmode transparent/opaque
		if(!isVersionOf_IE_AtLeast5_5() && (this.m_sWMode == "transparent" || this.m_sWMode == "opaque" ))
		{
			this.attachMouseWheelEvent(oHtmlElement, OwcFlashViewer_DHTML_onMouseWheel);
		}
	}

    function OwcFlashViewer_initControl()
    {
   		this.FlashDefaultObjId = generateUniqueID("FlashReader");
   		
		if (this.BaseClassMethod)
			this.BaseClassMethod.apply(this, arguments);
    }

	function OwcFlashViewer_parseControlHtml() {
		if (this.BaseClassMethod)
			this.BaseClassMethod.apply(this, arguments);

		var contentOptions = DHTML.getAttr( this.HtmlElement, Olive.Controls.attributes.FlashContentOptions );
		if( contentOptions ) 
		{
			this.m_oHtmlParams = this.parseParams( contentOptions );
		}

		this.m_bAllowTransparentOnMac = DHTML.getAttrBoolean(this.HtmlElement, Olive.Controls.attributes.AllowTransparentOnMac, this.m_bAllowTransparentOnMac);
		if(isMacintosh() && !this.m_bAllowTransparentOnMac)
		{
			this.m_sWModeForTransparency = "opaque";
		}
		var bgColor = DHTML.getAttr( this.HtmlElement, Olive.Controls.attributes.BgColor );
		if (bgColor)
		{
			if (bgColor.toLowerCase() == "transparent")
			{
				this.m_sWMode = this.m_sWModeForTransparency;
				bgColor = "";
			}

			this.bgColor = bgColor;
		}

		var sFirstPage = DHTML.getAttr( this.HtmlElement, Olive.Controls.attributes.FirstPage );
		if (sFirstPage)
		{
			sFirstPage = sFirstPage.toLowerCase();
			if((sFirstPage != OwcFlashViewer_WithHits) && (sFirstPage != OwcFlashViewer_OnEntity))
				this.reportKnownError(Olive.Errors.Code.InvalidHtmlAttrValue, Olive.Controls.attributes.FieldName, sFirstPage);
			else
				this.sFirstPage = sFirstPage;
		}
			
		gRefFlashReader = this;//??
	}

	function OwcFlashReader_parseParams( sParams ) {//static fn
		var retVal = {};
		var arrOptions = sParams.split( "||" );//sParams <--> "par1=val1||par2=val2||..."
		for ( var j = 0; j < arrOptions.length; j++ ) {
			arrOptions[ j ] = arrOptions[ j ].replace( /\|_/g, "|" );
			var arrOptionsSplit = arrOptions[ j ].split( "=" );
			if( arrOptionsSplit.length > 1 ) {
				retVal[ arrOptionsSplit[ 0 ] ] = arrOptionsSplit[ 1 ];
			}
		}
		return retVal;
	}

	function OwcFlashViewer_displayDocument( bHtmlPasteFlash, oAppArgParams )
	{
		// delete internal data at start of new display Document.
		//and not at the end of function because this data may be useful for post-initialisation events.
		this.m_nPageNo = null;
		this.m_sPrimId = null;
		this.m_sEntityId = null;
		this.m_sPageLabel = null;
		this.m_sCollection = null;
		this.m_sSearchStr = null;
		this.m_sLanguage = null;
		this.m_sQueryStr = null;
	
		if (oAppArgParams)
			this.m_oAppArgParams = oAppArgParams;

		var fvContentItem = this.getContentItem();
		if (fvContentItem)
		{
			if (fvContentItem.m_nFirstHitPage && this.sFirstPage == OwcFlashViewer_WithHits)//First page, with first hit.
			{
				this.m_nPageNo = fvContentItem.m_nFirstHitPage;
				fvContentItem.m_nPageNo = this.m_nPageNo;
			}
			else if (fvContentItem.m_nPageNo)
			{
				this.m_nPageNo = fvContentItem.m_nPageNo;
			}
			
			if (fvContentItem.m_sPrimId)
				this.m_sPrimId = fvContentItem.m_sPrimId;
			if (fvContentItem.m_sPageLabel)
				this.m_sPageLabel = fvContentItem.m_sPageLabel;

			// TODO: Move code to the OcwDataBound.js:
			// Find search paramerers
			var fvSearchQuery = null;
			var fvSearchResult = null;
			var fvDocument = null;

			for (var oDataItem = fvContentItem; oDataItem; oDataItem = oDataItem.m_oParentItem)
			{
				if (oDataItem.DataObjectType == OwcContentItem_Document)
					fvDocument = oDataItem;
				else if (oDataItem.DataObjectType == OwcContentItem_SearchResult)
					fvSearchResult = oDataItem;
				else if (oDataItem.DataObjectType == OwcContentItem_SearchQuery)
					fvSearchQuery = oDataItem.m_oSearchParams;
			} // {for} Find search paramerers

			if (fvSearchResult)
			{
				this.m_sCollection = fvSearchResult.m_sCollection;
				this.m_sEntityId = fvSearchResult.m_sEntityId;
				
				// Highlight primId for search results, (not from TOC search results)
				// when there are hits ONLY IN METADATA
				// otherwise delete primId and not send to the server
				// fvDocument exists only for TOC search results
				if (!fvDocument && fvSearchResult.m_nTotalHitsCount > 0 && fvSearchResult.m_nContentHitsCount != 0)
				{	
					this.m_sPrimId = null;
					fvContentItem.m_sPrimId = null;
					
				}
			}
			else if (fvContentItem.m_sCollection)
				this.m_sCollection = fvContentItem.m_sCollection;

			if (fvSearchQuery)
				this.readSearchQuery(fvSearchQuery);
		}

		// bHtmlPasteFlash : true - for new document
		//					false - for the same document but anoter pageNo or PrimId
		if (typeof(bHtmlPasteFlash) == "boolean")
			this.bHtmlPasteFlash = bHtmlPasteFlash;

		// if it's the same doc, call the server to get primitive box only; otherwise do paste-html with the flash <object>
		this.contentLoad();
	}

	function OwcFlashViewer_readSearchQuery(oSearchQuery)
	{
		this.m_sSearchStr = oSearchQuery.toString();
	}
	
	function OwcFlashReader_contentBuildControlParams(oParams)
	{
		var mergedParams = {};
		var qsParams = {};
		if (this.m_sQueryStr && this.m_sQueryStr!= "undefined")
			qsParams = this.parseParams( this.m_sQueryStr );

		var sParamName;
		for (sParamName in this.m_oHtmlParams)
			mergedParams[sParamName] = this.m_oHtmlParams[sParamName];
		for (sParamName in this.m_oAppArgParams)
			mergedParams[sParamName] = this.m_oAppArgParams[sParamName];
		for (sParamName in qsParams)
			mergedParams[sParamName] = qsParams[sParamName];

		for (sParamName in mergedParams)
			oParams.addParam(sParamName, mergedParams[sParamName]);

		if ( this.m_sPageLabel )
			oParams.addParam(this.UrlParam_Label, this.m_sPageLabel );
		if (this.m_sLanguage)
		{
			oParams.addParam("Language", this.m_sLanguage);
			var langLC = this.m_sLanguage.toLowerCase();
			if (langLC == "hebrew" || langLC == "ar" || langLC == "arabic")
				oParams.addParam("Hebrew", "1" ); // Right-to-left configuration
		} // {if} (this.m_sLanguage)

		// Add AppName to QS
		oParams.addParam("AppName", this.EP_APPLICATION_NAME);

		var flashObj = this.getFlashObjRef();

		//	Case, when arrived from goToPage or received DocHref identical
		//	to this.priorDocHref (or DocUid idential to this.priorDocUid) 
		//  and not need to change document, just a page.
		//	Navigate to page in current document.
		//	if LiveConect is not available reload flash object 
		//  the LiveConect verification , best to be placed logically in OwcFlashReader_passToFlashObj function
		if( !this.bHtmlPasteFlash )
		{
			//Process request to retrieve Primitive Box 
			oParams.addParam(this.UrlParam_RequestType, this.UrlParam_PrimitiveBox );
			oParams.addParam("callUid", "gotoPageWithHighlightingIntenal" );//TODO: implement callback
		}
		else 
		{
			oParams.addParam(this.UrlParam_DPBaseUrl, this.getDataProviderUrl());//"GetContent.asp"
			oParams.addParam(this.UrlParam_DPType, Olive.Controls.controlTypeNames.FlashViewer );
			oParams.addParam(this.UrlParam_RequestType, this.UrlParam_LoadFlash );
			if (isMozilla() )
			{
			    oParams.addParam(OwcUrlParam_IsMozilla, true, true);
			}

			if (this.m_sEntityId)
				oParams.addParam("EntityId", this.m_sEntityId, true);
		}
	}

	function OwcFlashReader_contentLoad()
	{
		if (!this.bHtmlPasteFlash)
		{
		    //if search 
		    if(this.m_sSearchStr)
		       this.HighlightSearchResults();
		    else
		    {   
				if (!this.getContentItem().m_nPageNo)
					this.getContentItem().m_nPageNo = "1";
				this.BaseClassMethod.apply(this, arguments);
			}
			return;
		}

		if (!this.contentCanLoad())
			return;
			
        this.setDocumentLoaded(false);
        this.objChunksDataStorage = new Object(); // clear previous chunks data.
        
		var oParams = new QueryString();
		// ActionsScript code has a bug - it has case sensitive URL API
		oParams.m_bCaseSensitive = true;
		this.contentBuildParams(oParams);
		if (this.contentBuildControlParams)
			this.contentBuildControlParams(oParams);
			
        if(this.m_sSearchStr)
        {
            //Add Flash event DocumentLoaded Listener. In purpose to send search request after viewer initialization.
            this.attachOwcEventHandler("documentLoaded",this.HighlightSearchResults_AfterLoad, this);
        }
        
		// Generate content of div container <object....>
		var htmlContent = this.generateHTMLContent(false, oParams);

		//--Clear before display
		if( this.HtmlElement )
			this.HtmlElement.innerHTML = "";//delete content

		//--Copy data to be displayed as HTML inside the component container
		var overflowBefore = this.HtmlElement.style.overflow.valueOf();
		this.HtmlElement.style.overflow = "";
		this.HtmlElement.innerHTML = htmlContent;
		this.HtmlElement.style.overflow = overflowBefore;
		
		//--Set background color for BODY
		var body = this.HtmlElement.parentElement;
		if (body)
			body.bgColor = this.bgColor;
			
		this.flashObjRef = eval( "document." + this.FlashDefaultObjId );//document.getElementById(this.FlashDefaultObjId);
	}

	// Overloaded function, sending request to server.
	function OwcFlashViewer_sendRequestRaw(oHtmlContentTarget, sUrl, oPostData, sMethod, bAsync)
	{	
		// Create new request object and initialize it
		var oRequest = Olive.XHTTP.CreateRequest();
		oRequest.m_OwcControl = this;
		oRequest.onDataReceived = Olive.Controls.IDataBound.Request_onDataReceived;
		oRequest.onError = Olive.Controls.IDataBound.Request_onDataError;

		// Call application's hook
		if (this.WebApplication && this.WebApplication.hookSendRequest)
			this.WebApplication.hookSendRequest(oRequest);

		// Fire event
		var oEvent = this.createOwcEventObject("sendingRequest");
		oEvent.Request = oRequest;
		this.fireOwcEvent(oEvent);
		var bCancelDefaultAction = oEvent.cancelDefaultAction;
		Object_Destroy(oEvent);

		if (bCancelDefaultAction)
			return;	// Do not send request

		// Send request to server
		oRequest.load(sUrl, sMethod, bAsync, oPostData /*, sUsername, sPassword*/);
	} // Olive.Controls.FlashReader.sendRequestRaw()

	function OwcFlashReader_processResponse(oRequest){
		var oEvent = this.createOwcEventObject("dataReceived");
		oEvent.Request = oRequest;
		this.fireOwcEvent(oEvent);
		Object_Destroy(oEvent);

		// Parse response text
		this.parseResponseText(oRequest);

		// Process analytical data returned in response
		if (oRequest.DataContent)
			this.gotoPageWithHighlightingIntenal(unescape( oRequest.DataContent), true );
		this.m_nPageNo = null;
		this.m_sPrimId = null;
	}

    /***************************************************************************
     * Function     : Olive.Controls.FlashViewer.gotoPageWithHighlighting()
     * Description  : go to specified page and highlight specified primitive.
     *                Used for "Open chapter from TOC control"
     * Parameters   : nPageNo - number of page to go to
     *                sPrimitiveId - Primitive id to highlight
     *                at least one of parameters must be defined.
     *                if only page deffined it will go to page without highlighting.
     *                if only sPrimitiveId deffined it will highlight primitive, and got to page which contains Primitive.
     * Return Value : boolean - return false if opperation cant be performed. Document wasn't loaded yet or invalid input parameters. 
    ***************************************************************************/
	function OwcFlashViewer_gotoPageWithHighlighting(nPageNo, sPrimitiveId, sEntityId, bRelativeNavigation, nContinuousScroll, bOpenGatefold)
	{
	    if (( !sPrimitiveId || sPrimitiveId == "") && (!sEntityId || sEntityId == ""))
	    {    // wrong parameters
	        if (typeof(nPageNo) == "string")
	        {
			    nPageNo = parseInt(nPageNo, 10);
			    if (isNaN(nPageNo))
			        return false;
			}
		    if (typeof(nPageNo) != "number")
			    return false;

            // send the command straightly to avoid getting event "flashGotoPage"
            this.sendCommandToFlashObj("gotoPageById", {'nPageNo':nPageNo, 'bRelativeNavigation':(!!bRelativeNavigation), 'nContinuousScroll':nContinuousScroll, 'bOpenGatefold':(!!bOpenGatefold)});
            return true;
	    }
	    
	    if(!this.getDocumentLoaded())//document wasn't loaded yet
	        return false;
	    var oContentItem = this.getContentItem();
	    oContentItem.m_sPrimId = sPrimitiveId;
	    oContentItem.m_nPageNo = nPageNo;
	    oContentItem.m_sEntityId = sEntityId;
	    this.bHtmlPasteFlash = false; //false - for the same document but anoter pageNo or PrimId
	    this.contentLoad();	    
	    return true;
	}//Olive.Controls.FlashViewer.gotoPageWithHighlighting()
	
	//primitive highlighting (navigation from TOC). TODO: call Flash directly -  Flash can calculate the primitive box
	function OwcFlashViewer_gotoPageWithHighlightingIntenal(sHighlightBox, bOpenGatefold)
	{
	    this.sendCommandToFlashObj("gotoPageWithHighlighting", {'sHighlightBox': sHighlightBox, 'bOpenGatefold':bOpenGatefold});
	}

    function OwcFlashViewer_onFlipAreaOrPageButtonClicked(oEvent)
    {
		/// <summary>
		///		Handler of the "FlipAreaOrPageButtonClicked" event of the Flash Viewer object (comes from Action Script).		
		/// </summary>
		/// <param name="oEvent" type="Olive.Event">
	    ///		Event arguments object.
	    /// </param>
		/// <remarks>
		///     the handler simply navigates to appropriate page according to sDirection value in the event.
		///     The handler is called if in FlashViewer defined HookNavigationToJs parameter. 
		///     This enables Javascript Control upon flash navigation events.
		/// </remarks>
		if (!oEvent)
	        return;
        
        var oNavigation = this.calculateDestinationPage(oEvent.sDirection, oEvent.nDestinationPage);
        this.gotoPageInternal(oNavigation.nPageNo, oNavigation.bRelativeNavigation, oEvent.nContinuousScroll, oEvent.bOpenGatefold);
    }
    
	function OwcFlashViewer_gotoPageInternal(nPageNo, bRelativeNavigation, nContinuousScroll, bOpenGatefold)
	{
        // fires event "flashGotoPage" to inform about commands "gotopage", "gotonextpage", "gotoprevpage" etc.
        var oEvent = this.createOwcEventObject("flashGotoPage");
		oEvent.nPageNo = nPageNo;
		oEvent.addCommand = null; // may be changed by handler
		this.fireOwcEvent(oEvent);
		
		// An additional command might be added
		var addCommand = oEvent.addCommand;
		// The action can be canceled and replaced by another action in event handler.
		var bCancelDefaultAction = oEvent.cancelDefaultAction; 		
		Object_Destroy(oEvent);
		if (bCancelDefaultAction)
		    return;
		
		if (addCommand)
		{
            // Workaround for the problem that action script could not get more than 1 command from javascript, if you are in
            // the event handler that came from flash ("flipAreaOrPageButtonClicked" - currently problematic place)
            // TODO: the solution is not nice, should be changed by implementation of transactions
            this.sendCommandsToFlashObj([{commandName:"gotoPageById", oDataParams:{'nPageNo':nPageNo, 'bRelativeNavigation':(!!bRelativeNavigation), 'nContinuousScroll':nContinuousScroll, 'bOpenGatefold':bOpenGatefold}},
                                         {commandName:addCommand.commandName, oDataParams:addCommand.params}]);
		}
		else
            this.sendCommandToFlashObj("gotoPageById", {'nPageNo':nPageNo, 'bRelativeNavigation':(!!bRelativeNavigation), 'nContinuousScroll':nContinuousScroll, 'bOpenGatefold':bOpenGatefold});
	}
	
	function OwcFlashViewer_cmdChangeModeDoublePage(newState, nPageNo)
	{
	    this.sendCommandToFlashObj("cmdChangeModeDoublePage",{'newState': newState, 'nPageNo': nPageNo});
	}
	
	function OwcFlashViewer_cmdChangeModeFlipAnimationEffect(newState)
	{
	    this.sendCommandToFlashObj("cmdChangeModeFlipAnimationEffect",{'newState': newState});
	}

	function OwcFlashViewer_cmdChangeModeHighlightTitles(newState)
	{
	    this.sendCommandToFlashObj("cmdChangeModeHighlightTitles",{'newState': newState});
	}
	
	function OwcFlashViewer_cmdChangeModeHighlightEntitiesOnMouseOver(newState)
	{
	    this.sendCommandToFlashObj("cmdChangeModeHighlightEntitiesOnMouseOver",{'newState': newState});
	}
	
	function OwcFlashViewer_cmdChangeModeMouseBehavior(newState)
	{
	    this.sendCommandToFlashObj("cmdChangeModeMouseBehavior",{'newState': newState});
	}

	function OwcFlashViewer_internalSetZoomFactor(nZoomFactor)
	{
	    this.sendCommandToFlashObj("setZoomFactor",{'nZoomFactor': nZoomFactor * 100});
	}
	
	function OwcFlashViewer_zoomFitWidth()
	{
	    this.sendCommandToFlashObj("zoomFitWidth",null);
	}

	function OwcFlashViewer_zoomFitHeight()
	{
	    this.sendCommandToFlashObj("zoomFitHeight",null);
	}

	function OwcFlashViewer_zoomFitWindow()
	{
	    this.sendCommandToFlashObj("zoomFitWindow",null);
	}

// Hits navigation
    function OwcFlashViewer_viewerGotoPrevHitPage()
    {   
        this.sendCommandToFlashObj("gotoPrevHitPage",null);  
    }

    function OwcFlashViewer_viewerGotoNextHitPage()
    {
        this.sendCommandToFlashObj("gotoNextHitPage",null);
    }

    function OwcFlashViewer_viewerGotoFirstHitPage()
    {
        this.sendCommandToFlashObj("gotoFirstHitPage",null);
    }

    function OwcFlashViewer_viewerGotoLastHitPage()
    {
        this.sendCommandToFlashObj("gotoLastHitPage",null);
    }
    
// Rotation
    function OwcFlashViewer_setRotationInternal(nRotation)
    {
        this.sendCommandToFlashObj("setRotation",{"nRotation": nRotation});
    }
	
// MouseMode functions	
	function OwcFlashViewer_setTextMouseMode()
	{
	    this.sendCommandToFlashObj("setTextMouseMode",null);
	}
	
	function OwcFlashViewer_setSmartZoomMouseMode()
	{
	    this.sendCommandToFlashObj("setSmartZoomMouseMode",null);
	}
	
	function OwcFlashViewer_setSimpleZoomMouseMode()
	{
	    this.sendCommandToFlashObj("setSimpleZoomMouseMode",null);
	}
	
    function OwcFlashViewer_setMouseMode(sNewMouseMode, bDoNotNotify)
    {
        if(typeof(sNewMouseMode) != "string")
            return false;
            
        switch(sNewMouseMode.toLowerCase())
        {
            case Olive.Controls.FlashViewer.MouseMode.Text:
            case Olive.Controls.FlashViewer.MouseMode.SmartZoom:
            case Olive.Controls.FlashViewer.MouseMode.SimpleZoom:
                break;
            default:
                return false;   // wrong parameters do not update.
        }
        this.m_sMouseMode = sNewMouseMode.toLowerCase();
        if(!bDoNotNotify)
            this.notifyCmdStateChanged();
        return true;
    }
	
	function OwcFlashViewer_getMouseMode()
	{
	    return this.m_sMouseMode;
	}
	
	function OwcFlashViewer_queryCmdUiState_MouseMode(oCmdUiState)
	{
	    var bEnableCommand = this.getDocumentLoaded();	
	    var bChecked = false;
		switch(oCmdUiState.commandName.toLowerCase())
		{
		    case "settextmousemode": 
		        bChecked = (this.getMouseMode().toLowerCase() == Olive.Controls.FlashViewer.MouseMode.Text)? true : false;
		    break;
		    case "setsmartzoommousemode":
		        bChecked = (this.getMouseMode().toLowerCase() == Olive.Controls.FlashViewer.MouseMode.SmartZoom)? true : false;
		    break;
		    case "setsimplezoommousemode":
		        bChecked = (this.getMouseMode().toLowerCase() == Olive.Controls.FlashViewer.MouseMode.SimpleZoom)? true : false;
		    break;
		    default: 
		        bEnableCommand = false;
		    break
		}

        oCmdUiState.checkCommand(bChecked);
		oCmdUiState.enableCommand(bEnableCommand);
		return false;
	}
// Following commands better to be implemented on application or page level
    function OwcFlashViewer_downloadPDF()
    {
        this.sendCommandToFlashObj("downloadPDF",null);
    }

    function OwcFlashViewer_print()
    {
        this.sendCommandToFlashObj("print",null);
    }

    function OwcFlashViewer_about()
    {
        this.sendCommandToFlashObj("aboutInfo",null);
    }

    function OwcFlashViewer_saveForOffline()
    {
        this.sendCommandToFlashObj("saveForOffline",null);
    }

    function OwcFlashViewer_toggleTOC()
    {
        this.sendCommandToFlashObj("toggleTOC",null);
    }

    function OwcFlashViewer_sendCommandToPlugIn(sPlugInID, sFunctionName, sJSONArgument)
    {
        this.sendCommandToFlashObj("sendCommandToPlugIn",{'sPlugInID': sPlugInID, 'sFunctionName': sFunctionName, 'sJSONArgument': sJSONArgument});
    }

	function OwcFlashViewer_sendCommandToFlashObj(sCommandName, oDataParams)
	{
	    //CommandID = sCommandName;
		var xmlCommandData = '<?xml version="1.0" encoding="utf-8" ?>'
						+ '<Command>'
						+ '<Param NAME="CommandID">' + sCommandName + '</Param>';
		for(var sPropName in oDataParams)
		{
		    var oPropValue = oDataParams[sPropName];
		    xmlCommandData += '<Param NAME="'+ sPropName +'">' + oPropValue +'</Param>';
		}				
						
		xmlCommandData += '</Command>';
		this.passToFlashObj("APIProvider",xmlCommandData);
	}
	
	function OwcFlashViewer_sendCommandsToFlashObj(arrCommands)
	{
		var xmlCommandData = '<?xml version="1.0" encoding="utf-8" ?>'
						+ '<Commands>';
        for (var i = 0; i < arrCommands.length; ++i)
        {
            var currentCommand = arrCommands[i];
            var sCommandName = currentCommand.commandName;
            xmlCommandData += '<Command>' + '<Param NAME="CommandID">' + sCommandName + '</Param>';
            
            var oDataParams = currentCommand.oDataParams;
            for (var sPropName in oDataParams)
	        {
	            var oPropValue = oDataParams[sPropName];
	            xmlCommandData += '<Param NAME="'+ sPropName +'">' + oPropValue +'</Param>';
	        }
	        
	        xmlCommandData += '</Command>';
        }
        			
		xmlCommandData += '</Commands>';
		this.passToFlashObj("APIProvider",xmlCommandData);
	}
	
	/************************************************************* 
	*	Method, send to flash object event to close TOC.
	*	Which actually simulates click on TOC toolbar button.
	*   Use it allong with flash toolbar.
	****************************************************************/
	function OwcFlashReader_closeTOC()
	{
        this.toggleTOC();
		if( this.flashObjRef && this.flashObjRef.focus )
		{
			DHTML.focus(this.flashObjRef);
		}
	}

	/************************************************************* 
	*	Method, send to flash object event to close TOC.
	*	Which actually simulates click on TOC toolbar button.
	****************************************************************/
	function OwcFlashViewer_clearSearchHits()
	{
	    this.sendCommandToFlashObj("clearSearchHits",null);
	}
	
	function OwcFlashViewer_loadSearchHits(nPageNo, sPageLabel, sSearchQuery, bLoadHitsForDocument, sEntityId, sPrimId)
	{
	    var searchData = { 
	                        sSearchPhrase : encodeURIComponent((sSearchQuery)? sSearchQuery : this.m_sSearchStr),
	                        sEntityId : (sEntityId)? sEntityId : this.m_sEntityId,
	                        sPrimId : (sPrimId)? sPrimId : this.m_sPrimId,
	                        nPageNo : (nPageNo)? nPageNo : this.m_nPageNo,
	                        sPageLabel : (sPageLabel)? sPageLabel : this.m_sPageLabel,
	                        sDocCollection : ""
	                     };
	    
	    var sCommandId = "loadSearchHits";
	    if(typeof(bLoadHitsForDocument) != "boolean")// if undefined read from internal settings
	        bLoadHitsForDocument = this.getModeViewHitsForDocument();
	        
	    if(bLoadHitsForDocument)
	    {    
	       sCommandId = "loadSearchHitsForDocument";
	    }
	    
	    
	    this.sendCommandToFlashObj(sCommandId, searchData);		
    }	
    
	function OwcFlashViewer_loadSearchHitsForEntity(nPageNo, sPageLabel, sSearchQuery, sEntityId, sPrimId)
	{
        this.loadSearchHits(nPageNo, sPageLabel, sSearchQuery, false, sEntityId, sPrimId);	
    }	

    function OwcFlashViewer_loadSearchHitsForDocument(nPageNo, sPageLabel, sSearchQuery, sEntityId, sPrimId)
    {
        this.loadSearchHits(nPageNo, sPageLabel, sSearchQuery, true, sEntityId, sPrimId);	
    }

	//event handler, wraper
    function OwcFlashReader_HighlightSearchResults_AfterLoad(oEvent)//internal
    {
        //detach event handler
        this.detachOwcEventHandler("documentLoaded", this.HighlightSearchResults_AfterLoad, this);
        //call function to highlight hits
        this.HighlightSearchResults();
    }
    
	function  OwcFlashReader_HighlightSearchResults()//internal
	{   
	    if (!this.m_sSearchStr)
	        return;
	    if(this.m_nPageNo > 0)//PageNo deffined
	        this.loadSearchHits();
	    else
	    {
	        this.m_sSearchStr = null;
	        this.gotoPageWithHighlighting(this.m_nPageNo, this.m_sPrimId, this.m_sEntityId)//highlight entity caption
	    }
	    this.m_sSearchStr = null; // nulify for next requests.
	}
	/************************************************************* 
	*	Method, which create HTML content of Flash Object 
	*	and pass init parameters to Flash.
	*	Input: 
	*			- i_bIsProxyObj - boolean, if false(default value), 
	*				regular Flash object will be created.
	*				True - proxy Flash object will be created.
	*				(See explanation, why in passToFlashObj method)
	****************************************************************/
	function OwcFlashReader_generateHTMLContent( i_bIsProxyObj, oParams ) {
		var content, id, MovieClipSrc, height, width, bgColor = this.bgColor;
		
		id = this.FlashDefaultObjId;
		MovieClipSrc = this.FlashSourceUrl;
		height = "100%";
		width = "100%";
		
		oParams.addParam("SELF_ID", id);
		oParams.addParam("HTML_EVENT_HANDLER","OwcFlashReader_handleFlashEvent");
		oParams.removeParam(OwcUrlParam_Field);
		var sUrl = this.buildRequestUrl(oParams);//getContent.asp?.....&For=flashreader&.....

		content ="<OBJECT classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0'";
		content += "WIDTH='" + width + "' HEIGHT='" + height + "' id='" + id + "' ALIGN='' VIEWASTEXT>";
		content += "<PARAM NAME='movie' VALUE=\"" + sUrl + "\">";
		content += "<PARAM NAME='SCALE' value='noscale'>";
		content += "<PARAM NAME='salign' VALUE='LT'>";
		content += "<PARAM NAME='swLiveConnect' VALUE='true'>";
		content += "<PARAM NAME='quality' VALUE='high'>";
		content += "<param name='allowFullScreen' value='true' />";
		content += "<param name='allowScriptAccess' value='always' />";
		//wmode='opaque' parameter makes flash object to be rendered in html flow.
		content += "<param name='wmode' value='" + this.m_sWMode + "' />";

		//Param name must be changed
		//content += "<PARAM NAME=FlashVars VALUE='" + sUrl + "'><PARAM NAME=quality VALUE=high>";
		content += "<PARAM NAME=bgcolor VALUE='" + bgColor + "'>";
			content += "<EMBED  src=\"" + sUrl + "\" ";
			content += "quality='high' wmode='" + this.m_sWMode + "' bgcolor='" + bgColor + "' ";
			content += " WIDTH='" + width + "' HEIGHT='" + height + "' ";
			content += "NAME='" + id + "' " + "allowFullScreen='true' allowScriptAccess='always' ";
			content += "ALIGN='top' TYPE='application/x-shockwave-flash' PLUGINSPAGE='http://www.macromedia.com/go/getflashplayer' ";
			content += " scale='noscale' salign='LT'>";
			content += "</EMBED></OBJECT>";
		
		return content;
	}//generateHTMLContent()

	/************************************************************************
	*	Must be implemented, when interface between Flash obj
	*	and getContent.asp will be ready .
	*	... FlashObj --> sendREquest to getContent.asp --> contentCallback --> FlashObj...
	*	
	*	Input:	- elmContent, actuall data, passed to Flash Application;
	*			- requestId, Id of request, using for recognize receiving data;
	*			- callUid, uniq call Id, passed to Flash Application;
	*			- i_queryStr, optional, bring additional data.
	*************************************************************************/
	function OwcFlashReader_contentCallback( elmContent, requestId, callUid, i_queryStr ) {
		dataFrameObj.release();
		
		if( typeof(i_queryStr) != "undefined" &&  i_queryStr != "" )//Parse received query
			this.parseQueryString( i_queryStr.split( "|" ) );

		if (decodeURIComponent( elmContent.value ).indexOf("Media not") != -1)
			this.reportKnownError(Olive.Errors.Code.MediaNotInserted);

		// Pass received data by callUid to Flash
		this.passToFlashObj( callUid, decodeURIComponent( elmContent.value ) );
		
		if (typeof(this.oncontentload) == "function") {
			createEPEvent();
			EPEvent.srcComponent = this;
			EPEvent.requestId = requestId;
			this.oncontentload();
			releaseEPEvent();
		}
	}//OwcFlashReader_contentCallback()

	function OwcFlashReader_setFlashObjRef( i_objRef ) // Set Flash Application Object reference
	{
		if( typeof(i_objRef) != "undefined" &&
			i_objRef )
			this.flashObjRef = i_objRef;
		else//in case of i_objRef undefined and flash object exist
		{
			var refObj = eval("document." + this.FlashDefaultObjId);//document.getElementById(this.FlashDefaultObjId);
			if( this.HtmlElement && refObj )
				this.flashObjRef = refObj;
		}
	}

	function OwcFlashReader_getFlashObjRef() {
		return ( this.flashObjRef  ? this.flashObjRef : null );
	}

	/****************************************************** 
	*	Parse query string, received in contentCallback
	******************************************************/
	function OwcFlashReader_parseQueryString( i_queryArr ) 
	{
		for( var i=0; i < i_queryArr.length - 1; ++i ) {
			switch( i_queryArr[i].split("=")[0] ) {
				case "UrlFlashReader":
					this.urlFlashReader = i_queryArr[i].split("=")[1];	
					break;

				case "UrlLoader":
					this.urlLoaderSwfFile = i_queryArr[i].split("=")[1];	
					break;

				case "UrlReader":
					this.urlReaderSwfFile = i_queryArr[i].split("=")[1];	
					break;

				case "UrlSplash":
					this.urlSplashSwfFile = i_queryArr[i].split("=")[1];	
					break;

				case "UrlSkin":
					this.urlSkinSwfFile = i_queryArr[i].split("=")[1];	
					break;

				case "UrlEmpty":
					this.urlEmptySwfFile = i_queryArr[i].split("=")[1];	
					break;

				case "IISLess" :
					var strVal = i_queryArr[i].split("=")[1];
					if(strVal.indexOf("false") != -1 )
						this.bIsIISLessVersion = false;
					else
						if(strVal.indexOf("true") != -1 )
							this.bIsIISLessVersion = true;
					break;
		
				case "ReaderBGColor" :
					this.bgcolor = i_queryArr[i].split("=")[1];
					break;
			}//{switch}
		}//{for}	
	} // parseQueryString()

	/***************************************************** 
	*	FlashReader_DoFSCommand, 
	*	called, when Flash object wants communicate to outside,
	*	might be useful for test purposes.
	*	====================Deprecated=================
	*****************************************************/
	function FlashReader_DoFSCommand(command, args) {
		switch(command) {
		case "msg2":	//alert(args);
			flashApp.value += "\n" + args;
		break;
		}
	}//DoFSCommand(command, args)

	/******************************************************************************************
	*	Flash API have been called via this method.
	*	This method must be implemented for two ways of passing
	*	data to Flash:
	*		1) Regular, via SetVariable and TGotoFrame;
	*		2) If first method unavailable, page where placed Flash object, have been designed 
	*			with one more frame element(empty) and if need, additional Flash
	*			object will be created( by generateHTMLContent method with additional params ).
	*			Via that created Flash object parameters will be send to main Flash object.
	*	
	*	Input:
	*		- i_uid - requested uniq id;
	*		- i_data - arguments, if exist, actually data.
	*******************************************************************************************/
	function OwcFlashReader_passToFlashObj(i_uid, i_data)
	{
		var flashObj = null;
		flashObj = this.getFlashObjRef();

		if( !flashObj )	
			return;//fail, flsh object not found
		
		if (this.isLiveConnectAvailable(flashObj)) {
			if(isNaN(i_uid)) {
				//send event to flash
				flashObj.SetVariable("_root.mcSkin.mcJScript.jsaCommand", i_uid);
				flashObj.SetVariable("_root.mcSkin.mcJScript.jsCommXML", i_data);
				flashObj.TGotoFrame("_root.mcSkin.mcJScript", 2);
			} else {
				// send response to event which comes from flash
				var varUID = "_global." + this.EP_FlashUIDVarName;
				var varData = "_global." + this.EP_FlashDataVarName;
				
				flashObj.SetVariable( varUID, i_uid );
				flashObj.SetVariable( varData, i_data );
				flashObj.TGotoFrame("_root", 2);	
			}
		}
	}//passToFlashObj()

	// called by application scripts
	function OwcFlashReader_flashContainerHide() 
	{ 
		if(!this.HtmlElement || !this.m_bShown)
			return;
		this.divContainer_style_width = this.HtmlElement.style.width;//save styles, then set to 0
		this.divContainer_style_height = this.HtmlElement.style.height;
		this.HtmlElement.style.width = "0px";
		this.HtmlElement.style.height = "0px";
		this.m_bShown = false;
	}

	function OwcFlashReader_flashContainerShow()
	{
		if(!this.HtmlElement || this.m_bShown)
			return;
		this.HtmlElement.style.width = this.divContainer_style_width;//restore former styles
		this.HtmlElement.style.height = this.divContainer_style_height;
		this.m_bShown = true;
	}

	// from FlashSupport.js - check availability of flash object
	function OwcFlashReader_isLiveConnectAvailable(FlashObj)
	{
		var sDPBaseUrl = ""; //sXMLServicePath = ""; // Asher 200510
		var bLiveConnectAvailable = false;
		try {
			sDPBaseUrl = FlashObj.GetVariable("_root.DPBaseUrl");
			if (sDPBaseUrl  &&  (sDPBaseUrl == this.getDataProviderUrl()))
			{
				bLiveConnectAvailable = true;
			}
		}
		catch(x) {} //do nothing; bLiveConnectAvailable = false;
		return bLiveConnectAvailable;
	}

	function OwcFlashReader_processCustomFlashEvent(oCustomData)
	{
		//pure virtual function should be handled by user.
	}


	//from getBook.asp, called from ActionScript (menu cmd. File >>> Print)
	function evaluateJSCode(args) {
		eval(args);
	}
	

	function OwcFlashReader_getFlashEventDataString (sChunkData, sUID, nChunkNo, nTotalChunks)
    {
        if (!nTotalChunks || nTotalChunks <= 1) //Backward compatibility
            return sChunkData;

        // TODO: make use of sUID and nChunkNo, and get rid of assumption:
        // that all data chunks are come in correct order and there is no interference of diffrent requests.(implementation is subject to changed)
        if (!sChunkData)
            sChunkData = "";
        if (!this.objChunksDataStorage[sUID])
            this.objChunksDataStorage[sUID] = new Array();
        
        this.objChunksDataStorage[sUID].push(sChunkData); //add chunk to storage.   
        if (this.objChunksDataStorage[sUID].length == nTotalChunks)
        {
            var sResData = this.objChunksDataStorage[sUID].join("");//Combine all Data
            this.objChunksDataStorage[sUID] = null;          //Clear for next event.
            delete this.objChunksDataStorage[sUID];
            return sResData;
        }    
        return null;
    }
    
	/******************************************************************************
	* Function : OwcFlashViewer_synchronizeData()
	* Overview : Internal method synchronize internal data fields of javascript object with flash object
	* Parameters : oFlashEventData - the object with data received from flash event. in structure of: property name - property value.
	******************************************************************************/
    function OwcFlashViewer_synchronizeData(oFlashEventData)
    {
        var bDoNotNotify = true;
        for (var prop in oFlashEventData)
        {
            this.syncField(prop, oFlashEventData[prop], bDoNotNotify);
        }
        this.notifyCmdStateChanged();
    }
    
    function OwcFlashViewer_syncField(prop, value, bDoNotNotify)
    {
        
        switch(prop)
        {
            case "sBaseHref": this.setDocumentLoaded(true, bDoNotNotify);
                break;
            case "nPageNo": if (value != null) this.setPageNo(value, bDoNotNotify);
                break;
            case "nNumPagesDisplayed": this.setNumPagesDisplayed(value);
                break;
            case "bDoublePageMode": this.setModeDoublePage(value);
                break;
            case "bFlipAnimationEffect": this.setModeFlipAnimationEffect(value);
                break;
            case "bHighlightTitles": this.setModeHighlightTitles(value);
                break;
            case "bHighlightEntitiesOnMouseOver": this.setModeHighlightEntitiesOnMouseOver(value);
                break;
            case "bMouseBehaviorEnabled": this.setModeMouseBehavior(value);
                break;
            case "isRightToLeft": ;
                break;
            case "sDocumentTitle": ;
                break;
            case "nTotalPages": this.setTotalPagesCount(value);
                break;
            case "nZoom": this.setZoomFactor(value / 100, bDoNotNotify);
                break;
            case "sFitMode": this.setZoomFitMode(value);
                break;
            case "sMouseMode": this.setMouseMode(value);
                break;
            case "nFirstHitPage": this.setFirstHitPage(value, bDoNotNotify);
                                  this.setHitsDataLoaded(true, bDoNotNotify);
                break;
            case "nLastHitPage": this.setLastHitPage(value, bDoNotNotify);
                                 this.setHitsDataLoaded(true, bDoNotNotify);
                break;
            case "nRotation": this.setRotation(value, bDoNotNotify);
                break;
            case "arrPageLabels": this.setPageLabels(value);
                break;
            case "bHasOnePagePDF": this.m_bHasOnePagePDF = value;
                break;
            case "bHasDocumentPDF": this.m_bHasDocumentPDF = value;
                break;
        }        
    }
    
    function OwcFlashViewer_setPageLabels(arrLabels)
    {
        // check that array is full
        this.m_oMapPageLabels = arrLabels;
    }
	/******************************************************************************
	* Function : OwcFlashReader_DispatchFlashEvent()
	* Overview : This function is global and called from flash object 
	*			  to send event data to HTML.
	* Parameters : sSelfId - is ID of flash object which send the event
	*				sEventName - name of event to delegate.
	*				sChunkData - string defining data object.
	*				The string obeys following format:
	*				"{'stringProperty' : 'abc' , 'numericProperty' : 123}"
	******************************************************************************/
	function OwcFlashReader_DispatchFlashEvent(sEventName, sChunkData, sUID, sChunkNo, sTotalChunks)
	{
		var sReturnValue = "";
		if (!sEventName || sEventName == "")// essential parameters
			return sReturnValue;

		// create object with event data from string received from flash.
		var oFlashEventData = null;
		var nChunkNo = parseInt(sChunkNo,10);
        var nTotalChunks = parseInt(sTotalChunks,10);

        var sFlashEventObject = this.getFlashEventDataString(sChunkData, sUID, nChunkNo, nTotalChunks);
        if (sFlashEventObject == null)    //sDataString is not ready yet; (empty string is valid data content.)
            return sReturnValue;
            
		if (sFlashEventObject)
		{		
			eval("oFlashEventData = "+ sFlashEventObject +";");
		}
	    // fire common event
		var oEvent = this.createOwcEventObject("flashEventReceived");
		oEvent.oFlashEventData = oFlashEventData;
		this.fireOwcEvent(oEvent);
		
		if (sEventName.toLowerCase() != "richmediaplayed")
			this.synchronizeData(oFlashEventData);
		
		var bCancelDefaultAction = oEvent.cancelDefaultAction;
		Object_Destroy(oEvent);

		if (bCancelDefaultAction)
			return sReturnValue;	// Do not dispatch concrete event.
		
		//If event name is not registered, call custom handler.
		if(!this.getOwcEventsClass(sEventName))
		{
			//call custom event handler (virtual function)
			sReturnValue = this.processCustomFlashEvent(oFlashEventData);
			return sReturnValue;
		}
		
		switch(sEventName)
		{
		    case "documentLoaded":
                break;
            case "SearchHitsCleared":
                this.setHitsDataLoaded(false);//cleared
                break;
		}
		
		// Dispatch concrete event.
		var oEvent = this.createOwcEventObject(sEventName);
		oEvent.sFlashEventReturnValue = "";
		//Copy properties from data object to event object.
		for (var prop in oFlashEventData)
		{
			if(oEvent[prop] != undefined)	//to avoid overriding of essential event properties.
				continue;					// hypothetic name collisiones.
			oEvent[prop] =  oFlashEventData[prop];
		}
	    
		var result = this.fireOwcEvent(oEvent);
		sReturnValue = oEvent.sFlashEventReturnValue;
		var bCancelDefaultAction = oEvent.cancelDefaultAction;
		if (bCancelDefaultAction)
		{
		    Object_Destroy(oEvent);
		    return sReturnValue;
		}
		
		    
		switch(sEventName)
		{
            case "oldFlashPlayerVersion" : 
                      this.reportKnownError(Olive.Errors.Code.UpdateFlashPlayer, oEvent.sCurrentVersion, oEvent.sExpectedVersion, oEvent.sDownloadURL); //sCurrentVersion, sExpectedVersion, sDownloadURL
		        break;
		}
		Object_Destroy(oEvent);
		return sReturnValue;
	}//OwcFlashReader_DispatchFlashEvent

    
    function OwcFlashReader_handleFlashEvent(str)
    {
        var sSelfId, sEventName, sChunkData, sUID, sChunkNo, sTotalChunks;
        var arrArguments = str.split("\",\"");
        if (arrArguments.length == 6)
        {
            arrArguments[0] = arrArguments[0].substring(1);
            var sLast  = arrArguments[arrArguments.length - 1];
            arrArguments[arrArguments.length - 1] = sLast.substring(0, sLast.length - 1);        

        }
        else if (arguments.length == 6)
        {
            arrArguments = arguments;
        }
        else 
            return "";

        sSelfId = arrArguments[0];
        sEventName = arrArguments[1];
        sChunkData = unescape(arrArguments[2]);
        sUID    = arrArguments[3];
        sChunkNo = arrArguments[4];
        sTotalChunks = arrArguments[5];        
        
        
        
        var oFlashReaderCtrl = OwcGetControl(sSelfId, true); // retrieve flash reader controll by unique ID of flash object.
        if (oFlashReaderCtrl &&  oFlashReaderCtrl.dispatchFlashEvent)
            return oFlashReaderCtrl.dispatchFlashEvent(sEventName, sChunkData, sUID, sChunkNo, sTotalChunks);
    }

	// cross-browser cover fn for mousewheel event. TODO: move to OwcDHTML.js
	function OwcFlashViewer_attachMouseWheelEvent(rObject, rHandler, bUseCapture)
	{
		if (isMozilla())
			DHTML.attachEvent(rObject, "DOMMouseScroll", rHandler, bUseCapture); // FF
		else
			DHTML.attachEvent(rObject, "mousewheel", rHandler, bUseCapture); // IE, Safari
	}

	function OwcFlashViewer_DHTML_onMouseWheel(oEvent)
	{
        var oControl = OwcGetControlFromHtmlElem(this);
		if (!oControl)
			return;
		var nDelta = ( oEvent.detail ? -oEvent.detail : oEvent.wheelDelta / 40 ); // detail FF, wheelDelta IE/Safari
	    oControl.sendCommandToFlashObj("launchMouseWheel",{'nDelta': nDelta});
		DHTML.eventPreventDefaultAction(oEvent);
		DHTML.eventStopBubbling(oEvent);
	} // OwcFlashViewer_DHTML_onMouseWheel()

	JScript.Type.RegisterClass("Olive.Controls.FlashViewer", Olive.Controls.FlashViewer, Olive.Controls.Viewer);
	Olive.Controls.RegisterControlType(Olive.Controls.controlTypeNames.FlashViewer, Olive.Controls.FlashViewer);
} // Olive.Controls.FlashViewer class
