﻿/* 
Template for AS3 Question Widgets 
*/
import flash.external.ExternalInterface;
import com.adobe.captivate.widgets.*;
import com.adobe.captivate.events.*;

/*
Variable declarations 
*/
var m_WidgetMode : String = '';
var m_WidgetParam : String = null;
var m_QuestionTitle : String = "";
var m_QuestionText : String = "";
var m_VariableHandle;
var m_MovieHandle : CPMovieHandle = null;
var m_InternalResourceLoader : CPWidgetInternalResourceLoader = null;
var m_ExternalResourceLoader : CPWidgetExternalResourceLoader = null;
var m_UsedInternalResources:Array = new Array();
var m_UsedExternalResources:Array = new Array();
var m_EventHandle : IEventDispatcher = null;
var m_EditModeWidth : int = 411;
var m_EditModeHeight : int = 328;
var m_StageModeWidth : int = 411;
var m_StageModeHeight : int = 328;


/* Event Handlers */
this.addEventListener( "enterFrame", FuncOnEnterFrame );

try {
	if( true == ExternalInterface.available )
	{	
		/*
		Todo : Register all the ExternalInterface functions 
		*/
		ExternalInterface.addCallback( "isQuestion" , isQuestion );
		ExternalInterface.addCallback( "getQuestionTitle" , questionTitle );
		ExternalInterface.addCallback( "getQuestionText" , questionText );
		ExternalInterface.addCallback( "setQuestionTitle" , setQuestionTitle );
		ExternalInterface.addCallback( "setQuestionText" , setQuestionText );
		ExternalInterface.addCallback( "getInspectorParameters" , getInspectorParameters );
		ExternalInterface.addCallback( "setInspectorParameters" , setInspectorParameters );
		ExternalInterface.addCallback( "setParameters" , setParameters );
		ExternalInterface.addCallback( "cpSetValue" , cpSetValue );
		ExternalInterface.addCallback( "getEditModeWidth", getEditModeWidth); 
		ExternalInterface.addCallback( "getEditModeHeight", getEditModeHeight);
		ExternalInterface.addCallback( "IsReadyForSnapShot", IsReadyForSnapShot);
		ExternalInterface.addCallback( "getListOfUsedInternalResources", getListOfUsedInternalResources);		
		ExternalInterface.addCallback( "getListOfUsedExternalResources", getListOfUsedExternalResources);				
		ExternalInterface.addCallback( "SetExternalResources", SetExternalResources);		
		ExternalInterface.addCallback( "SetInternalResources", SetInternalResources);				
		ExternalInterface.addCallback( "GetWidgetAPIVersion", GetWidgetAPIVersion);				
		ExternalInterface.addCallback( "SetStageModeSize", SetStageModeSize);		
		ExternalInterface.addCallback( "SetCaptivateVersion", SetCaptivateVersion);		
		ExternalInterface.addCallback( "SetLanguage", SetLanguage);		
	}
} catch( e ) {
}

function FuncOnEnterFrame( inEvent : Event ) : void
{
	/*
	This function provides a sample code for handling values of Widget modes and parameters.
	*/
	var l_WidgetModeParam : String = m_WidgetMode;
	/*
	This variable will be provided by Captivate.
	*/
	if( null == l_WidgetModeParam )
	{
		l_WidgetModeParam = 'Stage';
	}
	if( 'Edit' == l_WidgetModeParam )
	{
		/*
		This mode is used for setting properties of the widget inside Captivate during authoring time.
		*/
	}
	else if( 'Preview' == l_WidgetModeParam )
	{
		/*
		This mode is used for previewing the Widget in the preview window of widget panel.
		*/
	}
	else
	{
		/*
		This mode is used while previewing the widget inside Captivate during authoring or during execution.
		*/
		if( m_MovieHandle != null ) 
		{
			m_WidgetParam = m_MovieHandle.widgetParams();
		}
		if( m_WidgetParam != null )//at runtime inside Captivate movie
       	{
			var myXml:XML = new XML(m_WidgetParam);
		}
	}
}

/* 
Captivate will not recognize a Question Widget unless this function is implemented and returns true. 
*/
function isQuestion() : Boolean
{
	return true;
}

/*
This function is called by Captivate to obtain values from the Widget SWF.
This is the recommended method of passing values between Captivate and Widget SWF. 
Ideally an object is created and values assigned to parameters of the object.
This is taken by Captivate and stored as an xml string. 
*/
function getInspectorParameters() : Object
{
	var l_Parameters: Object = new Object();
	/*
	Todo : Set the data in l_parameters fields here.
	*/
	return l_Parameters;
}

/*
This function is called by Captivate after calling setParameters.
If the widget needs more time to update the SWF to draw on the stage
return false. When the SWF is ready, return true
*/
function IsReadyForSnapShot():Boolean
{
	return true;
}

/*
This function is called by Captivate to update the parameter values.
Parameters in the object passed to this function are saved
and the SWF is redrawn on the stage appropriately.
*/
function setParameters( inParam : Object ) : void
{
	if( null != inParam )
	{
		/*
		Todo : Save the parameters in object here 
		and Redraw the SWF.
		*/	
	}
}

/*
This function is called by Captivate when the widget is inserted.
Parameters in the object passed to this function are saved
and the SWF is redrawn on the stage appropriately.
*/
function setInspectorParameters( inParam : Object ) : void
{
	if ( null != inParam )
	{
		/*
		Todo : Save the parameters in object here 
		and Redraw the SWF.
		*/	
	}
}

/*
This function is called by Captivate during execution.
This sets the variables needed by the SWF for execution.
*/
function cpSetValue( inVariable : String, inValue ) : void
{
	if( 'movieHandle' == inVariable ) 
	{
		/* 
		m_VariableHandle can be used to access the variables from Captivate during execution.
		Eg: m_VariableHandle.rdcmndPause = 1; 
		will pause Captivate.
		Save the variable handle here.
		*/
		m_MovieHandle = CPMovieHandle(inValue);
		if(m_MovieHandle)
		{
			var l_MovieProps:CPMovieProperties = m_MovieHandle.getMovieProps();
			if(l_MovieProps)
			{
				m_VariableHandle = l_MovieProps.variablesHandle;
				if(m_EventHandle == null)
				{
						m_EventHandle = l_MovieProps.eventDispatcher;
						if(m_EventHandle != null)
						{
							/*Add The event listeners here which listen to different captivate events*/
						}
				}
			}
		}
	}	
	else if('internalResourceLoader' == inVariable) 	
	{
	   /*
	      m_InternalResourceLoader can be used to browse resoruce and load them into widet
       */ 	   
	    try
		{
			m_InternalResourceLoader = CPWidgetInternalResourceLoader(inValue);		
		}
		catch(e)
		{
			trace("exception in setting internal resource loader");
		}
		if(null == m_InternalResourceLoader )
		{
			trace("User Widget: m_InternalResourceLoader is null");
			return;
		}		
	}	
	else if('externalResourceLoader' == inVariable) 	
	{
	   /*
	      m_ExternalResourceLoader can be used to browse resoruce and load them into widet
       */ 	   
		try
		{
			m_ExternalResourceLoader = CPWidgetExternalResourceLoader(inValue);		
		}
		catch(e)
		{
			trace("exception in setting external resource loader");
		}
		if(null == m_ExternalResourceLoader )
		{
			trace("User Widget: m_ExternalResourceLoader is null");
			return;
		}		
	}	
	else if( 'widgetMode' == inVariable )
	{
		/*
		Save the Widget more here. 
		We may wish to do different things based on the Widget mode.
		We can draw the Widget differently on stage in Captivate and during execution.
		*/
		m_WidgetMode = inValue;
	}
}

/**
	Below functions are used to specify the width and height values of the widget parameters swf.
	If the widget parameters dialog should not be shown, return 0 from both these functions
*/
function getEditModeWidth( ): int
{
	return m_EditModeWidth;
}
function getEditModeHeight( ): int
{
	return m_EditModeHeight;
}

function questionTitle() : String 
{
	/*
	Todo : Provide a title for the Question
	*/
	return m_QuestionTitle;
}

function questionText() : String 
{
	/*
	Todo : Provide a Question text.
	*/
	return m_QuestionText;
}

function setQuestionTitle( inParam : Object ) : void
{
	/*
	Todo : Set the questioun title
	*/
	m_QuestionTitle = inParam.Text;
}

function setQuestionText( inParam : Object ) : void
{
	/*
	Todo : Set the question text.
	*/
	m_QuestionText = inParam.Text;
}

/*
Functions below need to be implemented by a Question Widget to be part of Captivate's Quizzing framework.
*/

function answeredCorrectly( inIsSurvey : Boolean ) : Boolean 
{
	/*
	Todo : Write your code here ...
	*/
	return true;
}

function answersIncomplete( inMustAnswerAll : Boolean ) : Boolean 
{
	/*
	Todo : Write your code here ...
	*/
	return false;
}

function enableAnswers() 
{
	/*
	Todo : Write your code here ...
	*/
}

function disableAnswers() 
{
	/*
	Todo : Write your code here ...
	*/
}

function resetAnswer( inAnswerID : String , inChosenAnswer : String , inCorrectAnswer : String ) 
{
	/*
	Todo : Write your code here ...
	*/
}

function clearAnswers() 
{
	/*
	Todo : Write your code here ...
	*/
}

function answers():Array
{
	/*
	Todo : Write your code here ...
	*/

	var answers:Array = new Array();
	return answers;
}

function getWidgetQuestionState():String
{
	/*
	Todo : Write your code here ...
	*/

	var widgetQuestionState:String = new String();
	return widgetQuestionState;
}

function setWidgetQuestionState( val:String ):void
{
	/*
	Todo : Write your code here ...
	*/

}


function setAccessibility()
{	
	/*
	Todo : Write your code here ...
	*/
}
function SetStageModeSize( iWidth : int , iHeight : int) : void
{
	m_StageModeWidth = iWidth;
	m_StageModeHeight  = iHeight;

	/* Use this width and height to rescale/reposition the content for stage mode */
}


/** 
    set used internal resource, this will be called by captivate in stage mode ,runtime mode and  edit mode 
*/ 
function SetInternalResources( usedResources : Array ) : void
{
	m_UsedInternalResources = usedResources;

	if(null == m_UsedInternalResources) 
	{
		trace("m_UsedInternalResources == NULL ");
		//make sure that in this case, IsReadyForSnapShot() doesn't block and IsReadyForSnapShot() returns true only.
		return ;
	}
	if(m_UsedInternalResources.length < 1)
	{
		//make sure that in this case, IsReadyForSnapShot() doesn't block and IsReadyForSnapShot() returns true only.
	 	return ;
	}
	
	if(null == m_InternalResourceLoader )
	{
		trace("User Widget: m_InternalResourceLoader is null");
		//make sure that in this case, IsReadyForSnapShot() doesn't block and IsReadyForSnapShot() returns true only.
		return;
	}
	
	/* if you wish, redraw the widget as now you have list of used internal resource IDs */
}



/**
	getListOfUsed Internal Resource() function will be used by Captivate while publishing/previewing, to determine what resource widget would need.
*/

function getListOfUsedInternalResources( ): Array
{
    return m_UsedInternalResources;
}

/**
     a) AddToListOfUsedInternalResources(),
     b) RemoveFromUsedInternalResourcesList() & 
     c) ClearUsedInternalResourceList()

     Widget developer need to reponsibly make use of above three functions , to ensure that 
     1) Only those resource that are actually going to be needed in RunTime Mode, are added into the list, else final swf size could be big.
     2) Resources that are needed in runtime are not missed, if not taken care end-user will not be able to see/hear desired resource in runtime mode
     
     Clasic Example : You have a browse button in your widget, user browse 10 times to find the suitable image,
     he/she likes the 10th image, you as widget developer really do not want Captivate to push in all 9 images 
     to final out of captivate project. hence captivate will make a call to getListOfUsedResource() 
     and push in only those images to final SWF that widget developer intended.
     
*/

function AddToListOfUsedInternalResources( resourceID : int): Boolean
{
    var retVal : Boolean = false;
    var index: int = -1;

    for (var i:int = 0; i < m_UsedInternalResources.length; i++) 
    {
        if (m_UsedInternalResources[i] == resourceID) 
        {
            index = i;
            break;
        }  
    }

    if(index >= 0)
    {
        trace("AddToListOfUsedInternalResources: resource already exists");
        return retVal;
    }

    m_UsedInternalResources.push(resourceID);
    
    return true;
}

function RemoveFromUsedInternalResourcesList( resourceID : int): Boolean 
{
   var retVal : Boolean = false;
    var index: int = -1;
    for (var i:int = 0; i < m_UsedInternalResources.length; i++) 
    {
        if (m_UsedInternalResources[i] == resourceID) 
        {
            index = i;
            break;
        }  
    }
    if(index < 0)
    {
        trace("AddToListOfUsedInternalResources: resource doesn't exists");
        return retVal;
    }
    m_UsedInternalResources.splice(index,1);
    return true;
}

function ClearUsedInternalResourceList( ): void
{
     m_UsedInternalResources.splice(0,m_UsedInternalResources.length);
}

/** 
    set used external resource, this will be called by captivate in stage mode ,runtime mode and  edit mode 
*/ 

function SetExternalResources( usedResources : Array ) : void
{
	m_UsedExternalResources = usedResources;

	if(null == m_UsedExternalResources) 
	{
		trace("m_UsedExternalResources == NULL ");
		//make sure that in this case, IsReadyForSnapShot() doesn't block and IsReadyForSnapShot() returns true only.
		return ;
	}
	if(m_UsedExternalResources.length < 1)
	{
		//make sure that in this case, IsReadyForSnapShot() doesn't block and IsReadyForSnapShot() returns true only.
	 	return ;
	}
	
	if(null == m_ExternalResourceLoader )
	{
		trace("User Widget: m_InternalResourceLoader is null");
		//make sure that in this case, IsReadyForSnapShot() doesn't block and IsReadyForSnapShot() returns true only.
		return;
	}
	
	/* if you wish, redraw the widget as now you have list of used external resource IDs */
}




/**
	getListOfUsed Internal Resource() function will be used by Captivate while publishing/previewing, to determine what resource widget would need.
*/

function getListOfUsedExternalResources( ): Array
{
    return m_UsedExternalResources;
}

/**
     a) AddToListOfUsedExternalResources(),
     b) RemoveFromUsedExternalResourcesList() & 
     c) ClearUsedExternalResourceList()

     Widget developer need to reponsibly make use of above three functions , to ensure that 
     1) Only those resource that are actually going to be needed in RunTime Mode, are added into the list, else final swf size could be big.
     2) Resources that are needed in runtime are not missed, if not taken care end-user will not be able to see/hear desired resource in runtime mode
     
     Clasic Example : You have a browse button in your widget, user browse 10 times to find the suitable image,
     he/she likes the 10th image, you as widget developer really do not want Captivate to push in all 9 images 
     to final out of captivate project. hence captivate will make a call to getListOfUsedResource() 
     and push in only those images to final SWF that widget developer intended.
     
*/

function AddToListOfUsedExternalResources( resourceID : int): Boolean
{
    var retVal : Boolean = false;
    var index: int = -1;

    for (var i:int = 0; i < m_UsedExternalResources.length; i++) 
    {
        if (m_UsedExternalResources[i] == resourceID) 
        {
            index = i;
            break;
        }  
    }

    if(index >= 0)
    {
        trace("AddToListOfUsedExternalResources: resource already exists");
        return retVal;
    }

    m_UsedExternalResources.push(resourceID);
    
    return true;
}

function RemoveFromUsedExternalResourcesList( resourceID : int): Boolean 
{
   var retVal : Boolean = false;
    var index: int = -1;
    for (var i:int = 0; i < m_UsedExternalResources.length; i++) 
    {
        if (m_UsedExternalResources[i] == resourceID) 
        {
            index = i;
            break;
        }  
    }
    if(index < 0)
    {
        trace("AddToListOfUsedExternalResources: resource doesn't exists");
        return retVal;
    }
    m_UsedExternalResources.splice(index,1);
    return true;
}

function ClearUsedExternalResourceList( ): void
{
     m_UsedExternalResources.splice(0,m_UsedExternalResources.length);
}

function SetCaptivateVersion( iMajorVersion : int , iMinorNumber : int) : void
{
	//Captivate will call this function in Stage mode and Edit mode
	// Widget developer can make use of it, if she/he wish to
}

function SetLanguage( iLanguage : String) : void
{
	//Captivate will call this function in Stage mode and Edit mode, to let Widget know the language
	// Widget developer can make use of it, if she/he wish to.
	// following values can be set by captivate
	//"en_US"
	//"en_GB"
	//"en_CA"
	//"da_DK"
	//"de_DE"
	//"es_ES"
	//"fr_FR"
	//"it_IT"
	//"nl_NL"
	//"no_NO"
	//"pt_BR"
	//"pt_PT"
	//"sv_SE"
}

function GetWidgetAPIVersion() : int
{
	return 2;
	// If returned less 2, this would cause Widget APIs, that are introduced in CP6, to not work
	// returning more than two will not be supported by Captivate 6.0, future versions may support it
	//0 : CP 5.0 
	//1 : CP 5.5 
	//2 : CP 6.0 
}
