/*!
**********************************************************************
@file InstallerSession.js

Copyright 2003-2006 Adobe Systems Incorporated.                     
All Rights Reserved.                                                
                                                                    
NOTICE: All information contained herein is the property of Adobe   
Systems Incorporated.                                                                                                                    

***********************************************************************
*/

// The property that will exist in the returned JSON object that denotes an error
var kError = "_error";


/**
The installer session object.  InstallerSession is subclass of
ContainerProxy for convenient access to the container methods
which this class makes heavy use of.
*/
function InstallerSession()
{
	/** A union of Session and CAPS InstallerPayloads, indexed by payload AdobeCode. Combo of already installed stuff and current setup stuff.*/
	this.allPayloads = new Object;
	
	/** InstallerPayloads in this session, indexed by payload AdobeCode. */
	this.sessionPayloads = new Object;
	
	/** The collection that represents this session, initialized by CreatePayloadSession */
	this.sessionCollection = null;
	
	/** A union of this Session and all CAPS collections, indexed by CollectionID */
	this.allCollections = new Object;
	
	/** raw session data returned from container during CreatePayloadSession() */
	this.sessionData = null;
	
	/** raw caps data returned from container during CreatePayloadSession() */
	this.capsMap = null;
	
	/** System Info */
	this.systemInfo = this.GetSystemInfo();	

	/** Commandline arguments */
    this.commandLineArgs = this.GetCommandLineArguments();

	/** Legacy...migrate to using this.sessionPayloads[adobeCode].GetSessionData() */
	this.payloadMap = this.GetSessionData().payloadMap;
	
	/** Object that stores installer properties such as EULA selected state, SN#, etc */
	this.properties = this.GetDefaultProperties();
	
	/** Augment the default property list with a few things for page localization */
	this.defaultProperties = this.GetDefaultProperties();

	/** Map of AdobeCodes to error log messages */
	this.errorMessages = new Object();
	
	/** Session creation error messages, usually fatal, with {error_string_code, default_string} pair */
	this.sessionErrorMessages = new Array();
	
	/** Supported ISO codes for the current collection of payloads.  This will be initialized
	 	in the first call to GetSupportedLanguagesArray()*/
	this.sessionSupportedLanguages = null;
	
	/** Have payload attributes been updated ? */
	this.payloadOptionsUpdated = false;
	
	/** Will be initialized in getWorkflowmode(), called in AhmbedGUIWorkflow() **/
	this.workflowMode=null;
	
	/** Used to determine if the payload policy has been inited or not **/
	this._PayloadPolicyInitMode = null;
	
	/** x64 Exception paylaods. All payloads which are x64 and excluded on x86 */
	this.x64ExceptionPayloads = new Object();
	
	/** Have any errors occured after Setup completes. Used to determine UI */
	this._hasCriticalPayloadFailures = false;
	this._hasRequiredPayloadFailures = false;
	this._hasRecommendedPayloadFailures = false;

	/** AFL language. ot_OT implies mul */
	this.aflLanguage = kMultiLingualIsoCode;
	
	this._hasUserCancelled = false;
	
	/** List of languages already installed for the session*/
	this.installedLanguages = null;
}


/**
InstallerSession is subclass of ContainerProxy.
*/
InstallerSession.prototype = new ContainerProxy();


/**
Get currently installed languages
Enumerate all language packs and then get install state of each langpack
A language is previously installed if any one of the language pack is previously installed.
*/
InstallerSession.prototype.GetInstalledLangaugesForSession = function ()
{
    if(this.installedLanguages == null)
    {
        this.installedLanguages = new Object();
        this.installedLanguages.count = 0;
        var payloadMap = this.sessionData.payloadMap;
	    for (var adobeCode in payloadMap)
	    {
		    var aPayload = payloadMap[adobeCode];
		    if((aPayload.isExtensionPayload == "1") && (aPayload.Extends.type=="langPack"))
		    {
		        //Check if the payload was installed for this session
		        var payload = this.allPayloads[adobeCode];
		        if(payload && payload.GetInstallStateForCollection(this.sessionCollection) == kCapsInstallStateInstalled)
		        {
		            var curLanguages;
				    curLanguages = aPayload.Languages;
				    for (var j = 0;  j < curLanguages.length; ++j)
				    {
					    this.installedLanguages[ curLanguages[j] ] = true;
					    ++this.installedLanguages.count;
				    }	        
		        }
		    }
		 }       
    }
    
    //No Language Packs?? Then we mark all languages as installed, so repair happens irrespective of what lanaguge is chosen.
    if(this.installedLanguages == null || this.installedLanguages.count < 1)    
    {
        this.installedLanguages = new Object();
        var langList = this.GetSupportedLanguagesArray();
        for(var i = 0; i < langList.length; ++i)
            this.installedLanguages[ langList[i] ] = true;
    }
    
    return this.installedLanguages;
}

/**
Calculate the set of supported languages and return the set as an array of ISO codes
*/
InstallerSession.prototype.GetSupportedLanguagesArray = function(inUICallbackObject)
{
	if (this.sessionSupportedLanguages == null)
	{
		this.sessionSupportedLanguages = new Array();
			
		var mapFamilyNameToLangs = new Object();
		var mapFamilyNameToLangIndep = new Object();

		for (var adobeCode in this.payloadMap)
		{
			var payload = this.payloadMap[adobeCode];
			var satisfiesObj = this.payloadMap[adobeCode].Satisfies;
		
			var keyPair = satisfiesObj.family + satisfiesObj.productName;
			
			if((payload.MediaInfo && payload.MediaInfo.mediaAvailable != "1"))
			    continue;
			    
			if(payload.isExtensionPayload == "1" && payload.Extends.type=="langPack" )

			{
				if(payload.Extends.type=="langPack")
				{
					var parentObj = this.payloadMap[adobeCode].Extends;
					keyPair = parentObj.family + parentObj.productName;
					//Check if the parent object of this lang pack has already initialized its langauges
					var langs = mapFamilyNameToLangs[keyPair];
					if(langs == null)
					{
						//parent has not entered any language, 
						//it seems the extension payload does not have a parent so we need to skip
						continue;
					}
					
				}
				else
				{
					//Other extensions does not participate in language determination
					continue;
				}
				//Skip the language pack this time.
				continue;

			}
			
			var langs = mapFamilyNameToLangs[keyPair];
			if (langs == null)
			{
				langs = new Object();
			}
			mapFamilyNameToLangIndep[keyPair] = false;

			// Update the langs object
			if (payload.isLanguageIndependent != null &&
				true == payload.isLanguageIndependent)
			{
				var allLangs = getAllSupportedLanguagesArray();
				for (var langIndex = 0; langIndex < allLangs.length; ++langIndex)
				{
					langs[allLangs[langIndex]] = 1;
				}
				mapFamilyNameToLangIndep[keyPair] = true;

			}
			else
			{
				for (var langIndex = 0; langIndex < payload.Languages.length; ++langIndex)
				{
					langs[payload.Languages[langIndex]] = 1;
				}
			}
			mapFamilyNameToLangs[keyPair] = langs;
		}	
		//We will run the checks again for all language packs
		for (var adobeCode in this.payloadMap)
		{
			var payload = this.payloadMap[adobeCode];

			if(payload.isExtensionPayload != "1"  || payload.Extends.type!="langPack" || (payload.MediaInfo && payload.MediaInfo.mediaAvailable != "1"))
			{
				//Skip all non language pack payloads, since they are already processed
				continue;
			}

			var parentObj = this.payloadMap[adobeCode].Extends;
			keyPair = parentObj.family + parentObj.productName;
			//Check if the parent object of this lang pack has already initialized its langauges
			var langs = mapFamilyNameToLangs[keyPair];
			if(langs == null)
			{
				//parent has not entered any language, 
				//it seems the extension payload does not have a parent so we need to skip
				continue;
			}			

			if(mapFamilyNameToLangIndep[keyPair] == true)
			{
			    // Delete all the language from parent since it was language independent and 
			    // supported languages are deteremined by the langauge packs
			    delete langs;
			    langs = new Object();
			    delete mapFamilyNameToLangs[keyPair];
			    mapFamilyNameToLangs[keyPair] = new Object();
			    mapFamilyNameToLangIndep[keyPair] = false;
			}

			for (var langIndex = 0; langIndex < payload.Languages.length; ++langIndex)
			{
				langs[payload.Languages[langIndex]] = 1;
			}

			mapFamilyNameToLangs[keyPair] = langs;
		}

		var firstIteration = true;
		for (var keyPair in mapFamilyNameToLangs)
		{
			this.LogDebug("Testing keypair languages: " + keyPair);
			// Get all the languages and intersect that with the existing set
			if (firstIteration)
			{
				var supportedLangMap = mapFamilyNameToLangs[keyPair];
				for (var eachSupportedLang in supportedLangMap)
				{
					this.sessionSupportedLanguages.push(eachSupportedLang);
				}
				firstIteration = false;	
			}
			else
			{
				if (this.sessionSupportedLanguages.length <= 0)
				{
					break;	
				}
				// Remove any element that doesn't exist
				var updatedSupportedLangs = new Array();
				for (var supportedIndex = 0; supportedIndex < this.sessionSupportedLanguages.length; ++supportedIndex)
				{
					if (mapFamilyNameToLangs[keyPair][this.sessionSupportedLanguages[supportedIndex]] != null)
					{
						updatedSupportedLangs.push(this.sessionSupportedLanguages[supportedIndex]);
					}
					else
					{
						this.LogDebug("Removing language from working set: " + this.sessionSupportedLanguages[supportedIndex]);
					}
				}
				this.sessionSupportedLanguages = updatedSupportedLangs;
			}		
		}
		this.LogDebug("Supported languages: " + this.sessionSupportedLanguages.toString());
	
		if (this.sessionSupportedLanguages.length <= 0)
		{
			if (inUICallbackObject && inUICallbackObject.onEmptyLanguageSet)
			{
				inUICallbackObject.onEmptyLanguageSet();
			}
		
		}
	}
	else
	{
		this.LogDebug("Using cached language set");
	}
	return this.sessionSupportedLanguages;
}


/**
Return an array of AdobeCodes for all payloads whose version isn't supported
by this RIBS host
@param  inContainerProxy    proxy interface object instance
@param  inPayloadMapObject  The JS object reprepresenting the payloads in the current session
@retval true                All payloads are supported by this version
@retval false               At least one payload version is not supported
*/
InstallerSession.prototype.GetUnsupportedVersionedPayloads = function(inUICallbackObj)
{
    this.LogDebug(FormatLogHeader("verifyPayloadVersioning"));
    
    var arrUnsupportedVersions = new Array();
    var versionObj = this.GetRIBSBuildInfo();

    this.LogInfo("Supported RIBS version range: [" + versionObj.Version.compatibleLowerBound + "," + versionObj.Version.compatibleUpperBound + "]");
 	for (var adobeCode in this.payloadMap)
    {
		var payload = this.payloadMap[adobeCode];
		
		//Check if the current payload is extension payload.
		//We skip version checking for extension payloads.
		if(payload.isExtensionPayload && payload.isExtensionPayload == "1")
		    continue;
		    
        this.LogDebug("Testing payload " + adobeCode + " built with RIBS version " + payload.version);
        if (compareVersions(payload.version, versionObj.Version.compatibleUpperBound) > 0 ||
            compareVersions(payload.version, versionObj.Version.compatibleLowerBound) < 0)
           {
				if (inUICallbackObj && inUICallbackObj.onUnsupportedVersion)
				{
					try
					{
						inUICallbackObj.onUnsupportedVersion(this, adobeCode);
					}
					catch (ex)
					{
						
					}
				}
                arrUnsupportedVersions.push(adobeCode);
           }
    }
    return arrUnsupportedVersions;
}

/**
Return an array of AdobeCodes for any incompatible payloads installed.  The array is empty if
there are no incompatible (same AdobeCode, different versions) payloads installed.
@param  inCAPSMapObject     CAPS payload map
@param  inUICallbackObject  Callback object to handle onIncompatiblePayload() event
@returns	Array of incompatible payloads.  Array is empty if not incompatible paylaods are installed
*/
InstallerSession.prototype.GetIncompatiblePayloadBuildsInstalled = function(inCAPSMapObject, inUICallbackObject)
{
    this.LogDebug(FormatLogHeader("GetIncompatiblePayloadBuildsInstalled"));
	
    var arrIncompatible = new Array();
 	for (var adobeCode in this.payloadMap)
    {
		var payload = this.payloadMap[adobeCode];
		sessionPayloadIdentifier = payload.BuildInfo.Created;
	        
		// Does this payload already exist in the CAPS data?
		var existingPayload = inCAPSMapObject.Payloads[adobeCode];
		if (existingPayload != null)
		{
			if (existingPayload.identifier != sessionPayloadIdentifier)
			{			
				try
				{
					if (inUICallbackObject && inUICallbackObject.onIncompatiblePayload)
					{
						inUICallbackObject.onIncompatiblePayload(this, adobeCode, sessionPayloadIdentifier, existingPayload.identifier);
					}
				}	
				catch (ex) 
				{
					this.LogDebug("inUICallbackObject.onIncompatiblePayload threw exception");
					this.LogDebug(ex);
				}		
				finally
				{
					arrIncompatible.push(adobeCode);
				}
			}
		}
	}   
    return arrIncompatible;
}


/**
Bind the payloads within this session to one another.  The second phase is 
to check the upgrades/conflicts given the bindings.

*/
InstallerSession.prototype.CreatePayloadSession = function(inUICallbackObj)
{
	//
	// Sanity check payload RIBS versions and build numbers
	//
	//var capsMapObject = this.GetCAPS();
	
				
	var sessionResolved = true;
	try
	{
	    //Check if we are in extensionOnly mode
        var commandLineArgs = this.commandLineArgs;
        
        //
		if (commandLineArgs && commandLineArgs.Properties && commandLineArgs.Properties.overrideFile)		
		{
			//Set the overrideFile path 
			this.properties["overrideFile"] = commandLineArgs.Properties.overrideFile;
		}

	
		this.LogDebug(FormatLogHeader("InstallerSession.CreatePayloadSession: Checking for unsupported payloads"));
		var retAdobeCodes = this.GetUnsupportedVersionedPayloads(inUICallbackObj);
		if (retAdobeCodes.length > 0)
		{
		    throw (new Array("sessionErrorUnsupportedPayloads", "Unsupported payload versions included"));
		}
		
		//
		// Create payload universe & graphs
		//
		this.allPayloads = new Object;
		this.sessionPayloads = new Object;
		this.allCollections = new Object;

		if (null == this.sessionData)
			this.sessionData = this.GetSessionData();

		if (null == this.payloadMap)
			this.payloadMap = this.sessionData.payloadMap;

        if (null == this.capsMap)
			this.capsMap = this.GetCAPS();


		
		// add session payloads to the payload universe allPayloads
		// and to sessionPayloads
		this.LogDebug(FormatLogHeader("InstallerSession.CreatePayloadSession: Checking session payloads"));
		var arrDriverConflicts = new Array();
		for (var anAdobeCode in this.sessionData.payloadMap)
		{
			var thePayload = new InstallerPayload(anAdobeCode);
			var aResult = thePayload.SetSessionData(this.sessionData.payloadMap[anAdobeCode]);										
			this.properties["MEDIATAG"] = thePayload.GetSessionData().ReleaseType;			
			thePayload.GetSessionData().tsInstalled = "";
			var isWin = (this.properties["platform"] == "Win32")?true:false;
			if(isWin)
			{
				var is64Bit = (this.systemInfo.Windows.Is64Bit == "1") ? true:false;			
				if(!thePayload.CheckBitnessForInclusion(is64Bit))
				{
					this.LogWarning("64-bit payload detected on x86 machine. Skipping this payload. AdobeCode:" + thePayload.GetAdobeCode() + " Product Name:" + thePayload.GetProductName());					
					this.x64ExceptionPayloads[anAdobeCode] = thePayload;
					continue;			
				}
			}
			
			if (commandLineArgs && commandLineArgs.Properties && commandLineArgs.Properties.extensionsOnly && commandLineArgs.Properties.extensionsOnly == "1")		
			{
				//Set the media path 
				if(commandLineArgs.Properties.extensionMediaPath)
				    this.properties["mediaPath"] = commandLineArgs.Properties.extensionMediaPath;
				this.properties["extensionsOnly"]=1;
				var arAdobeCodes = commandLineArgs.Properties.adobeCodeList.split(",");
				//Remove all payloads except these ones
				var bFound = false;
				for(var extnIndex=0; extnIndex < arAdobeCodes.length; ++extnIndex)
				{
				    if(arAdobeCodes[extnIndex] == anAdobeCode)
				    {
					    bFound = true;
					    break;
				    }
				}

				if(!bFound)
				    continue;

			}
			
			this.allPayloads[anAdobeCode] = thePayload;
			this.sessionPayloads[anAdobeCode] = thePayload;
			if (aResult != thePayload.kIntegrityOK)
			{				
				this.LogDebug("Invalid payload:");
				this.LogDebug(thePayload.GetAdobeCode());
				incompatiblePayloads++;
			}

			if (this.sessionData.driverPayloadID && 
				this.sessionData.driverPayloadID == anAdobeCode)
			{
				arrDriverConflicts = thePayload.GetRawConflicts();
			}			
		}
		
		
		// Any incompatible payloads installed?
		this.LogDebug(FormatLogHeader("InstallerSession.CreatePayloadSession: Checking incompatible payloads"));
		var retIncompatibleAdobeCodes = this.GetIncompatiblePayloadBuildsInstalled(this.capsMap, inUICallbackObj);
		if ((retIncompatibleAdobeCodes.length > 0) && !(this.IsUninstallMode()))
		{
		    throw (new Array("sessionIncompatiblePayloadsInstalled", "Incompatible payloads already installed"));
		}
		// add caps payloads to the payload universe and check for conflict relationships along the way				
		this.LogDebug(FormatLogHeader("InstallerSession.CreatePayloadSession: Checking already installed payloads"));
		for (var anAdobeCode in this.capsMap.Payloads)
		{
			this.LogDebug(anAdobeCode + " " + this.capsMap.Payloads[anAdobeCode].productName);
			var thePayload = this.sessionPayloads[anAdobeCode];
			if (null == thePayload)
			{
				thePayload = new InstallerPayload(anAdobeCode);
				this.allPayloads[anAdobeCode] = thePayload;
			}
			var aResult = thePayload.SetCAPSData(this.capsMap.Payloads[anAdobeCode]);
			
			try
			{
			    for(var indx=0; indx < this.capsMap.Payloads[anAdobeCode].Collections.length; ++indx)
			    {
                    if(this.capsMap.Payloads[anAdobeCode].Collections[indx].collectionID == this.sessionData.key)
                    {
                        thePayload.GetSessionData().tsInstalled = this.capsMap.Payloads[anAdobeCode].Collections[indx].tsInstalled;
                        break;
                    }
			    }
			}
			catch(ex)
			{
			
			}
			
			if (aResult != thePayload.kIntegrityOK)
			{
				this.LogDebug("Bad payload:");
				this.LogDebug(thePayload);
			}
			
			//Fetch the serial number stored in caps (in reinstall mode)
			if (this.sessionData.driverPayloadID && 
				this.sessionData.driverPayloadID == anAdobeCode)
			{
			    var capsSerial = thePayload.GetCAPSData().pers_EPIC_SERIAL;
			    if(capsSerial)
			        this.properties["pers_EPIC_SERIAL"] = capsSerial;
			}
			
			// Check the conflicts
			var capsConflicts = thePayload.GetRawConflicts();
			var index1 = index2 = -1;
			for (var k = 0; k < arrDriverConflicts.length && (-1 == index1); ++k)
			{
				if (arrDriverConflicts[k] == anAdobeCode)
				{
					index1 = k;	
				}
			}
			if (this.sessionData.driverPayloadID)
			{
				for (var k = 0; k < capsConflicts.length && (-1 == index2); ++k)
				{
					if (capsConflicts[k] == this.sessionData.driverPayloadID)
					{
						index2 = k;	
					}
				}				
			}
			if ((-1 != index1) || (-1 != index2))
			{
				doBootstrapUninstallCheck = true;
				// This is handle by PayloadPolicyNode and the system check page
				//throw (new Array("sessionErrorConflictingDriver", "You cannot install this product because a conflicting component is already installed."));
			}
		}
		
		if (commandLineArgs && commandLineArgs.Properties && commandLineArgs.Properties.extensionsOnly && commandLineArgs.Properties.extensionsOnly == "1")		
		{
		    for (var anAdobeCode in this.sessionPayloads)
		    {
		        var curPayload = this.sessionPayloads[anAdobeCode];
		        var rawUpgradeList = curPayload.GetRawUpgradeList();
                for (var index = 0; index < rawUpgradeList.length; ++index)
			    {
			        var payloadToUpgrade = this.sessionPayloads[rawUpgradeList[index]];
			        if(payloadToUpgrade == null)
			        {
			            curPayload.GetSessionData().tsInstalled = Date().toString();			    
			            var thePayload = new InstallerPayload(rawUpgradeList[index]);
                        var prevVersionData = this.sessionData.payloadMap[rawUpgradeList[index]];
                        if(prevVersionData != null) //Check if previous version is installed.
                        {
                            var aResult = thePayload.SetSessionData(prevVersionData);										
                            this.properties["MEDIATAG"] = thePayload.GetSessionData().ReleaseType;			
                            thePayload.GetSessionData().tsInstalled = "";	
                            this.allPayloads[rawUpgradeList[index]] = thePayload;
			                this.sessionPayloads[rawUpgradeList[index]] = thePayload; 
			                payloadToUpgrade = thePayload;
			            }
			        }
			        
				    if (payloadToUpgrade)
				    {
					    payloadToUpgrade.SetInstallerAction(kInstallerActionRemove);
					    payloadToUpgrade.beingUpgraded = true;
				    }
                }
            }	    			
		}
        
        // connect bidirectional conflict references between payloads
		for (var anAdobeCode in this.allPayloads)
		{
			var aPayload = this.allPayloads[anAdobeCode];
			var rawConflicts = aPayload.GetRawConflicts();

			for (var index = 0; index < rawConflicts.length; ++index)
			{
				var conflictingPayload = this.allPayloads[rawConflicts[index]];
				if (conflictingPayload)
				{
					aPayload.AddConflictingPayload(conflictingPayload);
					conflictingPayload.AddConflictingPayload(aPayload);
				}
			}
		}

		// if there is some other collection that has 
		// already installed a payload that upgrades us then we can't install this version
		var doBootstrapUninstallCheck = false;

		// connect upgrade relationships between payloads
		for (var anAdobeCode in this.allPayloads)
		{
			var aPayload = this.allPayloads[anAdobeCode];
			var rawUpgradeList = aPayload.GetRawUpgradeList();

			for (var index = 0; index < rawUpgradeList.length; ++index)
			{
				var payloadToUpgrade = this.allPayloads[rawUpgradeList[index]];
				if (payloadToUpgrade)
				{
					aPayload.AddPayloadToUpgradeFrom(payloadToUpgrade);
					payloadToUpgrade.AddPayloadToUpgradeTo(aPayload);
				}
				
				if (this.sessionData.driverPayloadID)
				{
					if (this.sessionData.driverPayloadID == rawUpgradeList[index])
					{
						// If something is already installed that upgrades us, then we're not
						// going to try to install this session
						// FIXME: This is handled in systemCheck.js in GUI mode.  Need to harmonize check with silent.
						if (!this.UIHosted())
						{
							doBootstrapUninstallCheck = true;
							throw (new Array("sessionErrorUpgradingPayloadInstalled", "A payload that upgrades the driver payload is already installed"));
						}
					}
				}
			}
		}

		// create requires/satisfies buckets for later resolution against
		// install choices in the session
	    	this.LogInfo(FormatLogHeader("Verify Dependency Subscribers"));
		var missingDependencyCount = 0;
		var x64CriticalException = 0;
		
		for (var anAdobeCode in this.sessionPayloads)
		{			
			var aPayload = this.sessionPayloads[anAdobeCode];			
			
			//Check and see if current payload has extension relationship with test payload
			if(aPayload.isExtensionPayload())					
			{
				var extAdobeCode=aPayload.GetSessionData().Extends.AdobeCode;				   
			    var dependencyObj = new Object();
				dependencyObj.family = aPayload.GetSessionData().Extends.family;
				dependencyObj.productName = aPayload.GetSessionData().Extends.productName;
				dependencyObj.minVersion = aPayload.GetSessionData().Extends.minVersion;

                for (var testAdobeCode in this.sessionData.payloadMap)
				{
					var testPayload = this.sessionPayloads[testAdobeCode];
					if(testPayload == null)
					{
					    testPayload = new InstallerPayload(testAdobeCode);
					}
					if(testPayload._sessionData == null)
					    var aResult = testPayload.SetSessionData(this.sessionData.payloadMap[testAdobeCode]);
					if(testPayload.SatisfiesDependency(dependencyObj) || (extAdobeCode == testAdobeCode))
					{
						aPayload.parentPayload = testPayload;
						break;
					}						
				}
				
				//Check if the payload does not have parent in current session.				
				if(aPayload.parentPayload == null)
				{
				    var errMsg = "The extension payload: " + aPayload.GetProductName() + "  " + aPayload.GetAdobeCode() + " requires a parent with following specification:" +
                    "\n\tFamily: " + dependencyObj.family + 
                    "\n\tProductName: " + dependencyObj.productName +
                    "\n\tMinVersion: " + dependencyObj.minVersion +
                    "\n\tThis parent relationship is not satisfied, because this payload is not present in this session." +
                    "\n\tThis payload will be ignored in this session.";                    
                    this.LogError(errMsg);		
                    delete this.sessionPayloads[anAdobeCode];
                    if(this.allPayloads[anAdobeCode])
                        delete this.allPayloads[anAdobeCode];
				}
			}
			
			//Initialize the UI Parent relationship
			if(aPayload.hasUIParent())					
			{
			    var dependencyObj = new Object();
				dependencyObj.family = aPayload.GetSessionData().UIParent.family;
				dependencyObj.productName = aPayload.GetSessionData().UIParent.productName;
				dependencyObj.minVersion = "";

                for (var testAdobeCode in this.sessionData.payloadMap)
				{
				    if(this.x64ExceptionPayloads[testAdobeCode] != null)
				        continue;
				   
					var testPayload = this.sessionPayloads[testAdobeCode];
					
					if(testPayload == null)
					{
					    testPayload = new InstallerPayload(testAdobeCode);
					}
					
					if(testPayload._sessionData == null)
					    var aResult = testPayload.SetSessionData(this.sessionData.payloadMap[testAdobeCode]);
					    
					if(testPayload.IsDriverForSession(this))    
					    continue;
                    //is the ui parent pointing to same payloads?
					if(testPayload.GetAdobeCode() == aPayload.GetAdobeCode())
					    continue;   
					if(testPayload.SatisfiesDependency(dependencyObj) )
					{
						aPayload.uiParentPayload = testPayload;
						break;
					}						
				}
				
				//Check if the payload does not have parent in current session.				
				if(aPayload.uiParentPayload == null)
				{
				    aPayload.GetSessionData().hasUIParent = "0";
				    var errMsg = "The payload: " + aPayload.GetProductName() + "  " + aPayload.GetAdobeCode() + " requires a UI parent with following specification:" +
                    "\n\tFamily: " + dependencyObj.family + 
                    "\n\tProductName: " + dependencyObj.productName +                    
                    "\n\tThis parent relationship is not satisfied, because this payload is not present in this session." ;                    
                    this.LogWarning(errMsg);		                   
				}
				else
				{
					aPayload.uiParentPayload.UIChildPayloads.push(aPayload);
				    var errMsg = "The payload: " + aPayload.GetProductName() + " has been added to the UIChild list of " + aPayload.uiParentPayload.GetProductName();
                    this.LogDebug(errMsg);		                   
				}
			}

			var unresolvedDependencies = aPayload.GetUnresolvedDependencies();
			for (var index = 0; index < unresolvedDependencies.length; ++index)
			{
				var aDependency = unresolvedDependencies[index];
				
				if(aDependency != null)
				    aDependency.satisfyingPayloads = new Object();
				    
				var satisfiesCount = 0;
				for (var testAdobeCode in this.sessionPayloads)
				{
					var testPayload = this.sessionPayloads[testAdobeCode];
					if (testPayload.SatisfiesDependency(aDependency))
					{
						aPayload.AddDependencySatisfier(aDependency, testPayload);
						++satisfiesCount;
					}					
				}
				if (satisfiesCount <= 0)
				{
					var bLogMissing = true;
					//Check if the dependency was in x64 exception list
					for (var testAdobeCode in this.x64ExceptionPayloads)
					{
						var testPayload = this.x64ExceptionPayloads[testAdobeCode];
						if (testPayload.SatisfiesDependency(aDependency))
						{
							bLogMissing = false;

							if(aDependency.type == kDependencyTypeRecommended)
							{
								this.LogWarning("The payload with AdobeCode:  " + anAdobeCode + " has recommended dependency on:");
								this.LogWarning("\tFamily: " + aDependency.family);
								this.LogWarning("\tProductName: " + aDependency.productName);
								this.LogWarning("\tMinVersion: " + aDependency.minVersion);
								this.LogWarning("\tThis dependency is not satisfied, because this payload is x64 and is not supported on this machine.");								
								this.LogWarning("\tRemoving this payload from the dependency list.");
							}
							else if(aDependency.type == kDependencyTypeRequired)
							{
								this.LogError("The payload with AdobeCode:  " + anAdobeCode + " has required dependency on:");
								this.LogError("\tFamily: " + aDependency.family);
								this.LogError("\tProductName: " + aDependency.productName);
								this.LogError("\tMinVersion: " + aDependency.minVersion);
								this.LogError("\tThis dependency is not satisfied, because this payload is x64 and is not supported on this machine.");								
								this.LogError("\tRemoving this dependency from list. Product may function improperly.");								

							}
							else
							{
								++x64CriticalException;								

								this.LogError("The payload with AdobeCode:  " + anAdobeCode + " has critical dependency on:");
								this.LogError("\tFamily: " + aDependency.family);
								this.LogError("\tProductName: " + aDependency.productName);
								this.LogError("\tMinVersion: " + aDependency.minVersion);
								this.LogError("\tThis dependency is not satisfied, because this payload is x64 and is not supported on this machine.");																
							}
						}
					}

					if(bLogMissing)
					{
						++missingDependencyCount;
						this.LogError("Unable to find a payload that satisfies " + anAdobeCode + " dependency on:");
						this.LogError("\tFamily: " + aDependency.family);
						this.LogError("\tProductName: " + aDependency.productName);
						this.LogError("\tMinVersion: " + aDependency.minVersion);
					}
				}
			}
		}
		if(x64CriticalException > 0)
		{
			doBootstrapUninstallCheck = true;
			throw (new Array("sessionErrorSessionDependenciesNotSatisfiedx64", "Some of the critical dependencies are x64 payloads, which are not supported on this machine."));		
		}
		if (missingDependencyCount > 0)
		{
			doBootstrapUninstallCheck = true;
			throw (new Array("sessionErrorSessionDependenciesNotSatisfied", "Session has dependencies that cannot be satisfied"));	
		}
	
		// create map of known CAPS collections.  
		this.LogDebug(FormatLogHeader("InstallerSession.CreatePayloadSession: Checking already installed sessions"));
		if (this.capsMap && this.capsMap.Collections)
		{
			for (var aCollectionID in this.capsMap.Collections)
			{
				var aCollection = this.capsMap.Collections[aCollectionID];
				aCollection.collectionID = aCollectionID;

				if (null != aCollection.driverPayloadID)
				{
					aCollection.driverPayload = this.allPayloads[aCollection.driverPayloadID];
					if (null == aCollection.driverPayload)
					{
						// This may have occurred if the driver payload was not successfully installed
						// due to a previous session dependency payload failing or the user canceling
						this.LogWarning("Driver payload specified for collection: " + aCollectionID + " but payload: " + aCollection.driverPayloadID + " not registered.");	
					//	throw (new Array("sessionErrorDriverPayloadNotFound", "Driver payload specified but not found"));						
					}
				}

				this.allCollections[aCollectionID] = aCollection;
			}
		}

		// add collection for this session if it doesn't already exist
		if (!this.sessionData.key)
			throw (new Array("sessionErrorSessionKeyMissing", "Session key is missing from session data"));
		this.sessionCollection = this.allCollections[this.sessionData.key];
		if (!this.sessionCollection)
		{
			this.sessionCollection = new Object;
			this.sessionCollection.collectionID = this.sessionData.key;

			if (this.sessionData.driverPayloadID)
			{
				this.sessionCollection.driverPayloadID = this.sessionData.driverPayloadID;
				this.sessionCollection.driverPayload = this.allPayloads[this.sessionCollection.driverPayloadID];
				if (!this.sessionCollection.driverPayload)
				{
					this.LogWarning("Driver payload specified for current collection: " + this.sessionCollection.collectionID + " but payload: " + this.sessionCollection.driverPayloadID + " not registered.");						
					//throw (new Array("sessionErrorDriverPayloadNotFoundThis", "Driver payload could not be found for this collection"));
				}
			}
			this.allCollections[this.sessionCollection.collectionID] = this.sessionCollection;
		}

		// add payloads to collections & vice versa.  while we're here we're going to check for installed payloads
		// that conflict with our AdobeCode
		for (var anAdobeCode in this.allPayloads)
		{
			var aPayload = this.allPayloads[anAdobeCode];
			var payloadCAPSData = aPayload.GetCAPSData();
			var addedSessionCollection = false;

			// add CAPS collections
			if (payloadCAPSData && payloadCAPSData.Collections)
			{
				for (var index = 0; index < payloadCAPSData.Collections.length; ++index)
				{
					var aPayloadCollection = payloadCAPSData.Collections[index];
					aPayloadCollection.payload = aPayload;

					var aCollection = this.allCollections[aPayloadCollection.collectionID];
					aPayloadCollection.collection = aCollection;

					if (!aCollection.payloadRecords)
						aCollection.payloadRecords = new Object;

					aCollection.payloadRecords[anAdobeCode] = aPayloadCollection;

					aPayload.AddCollectionRecord(aPayloadCollection);
					if (aPayloadCollection.collection == this.sessionCollection)
						addedSessionCollection = true;
				}
			}

			// if the session collection wasn't added and this is a session payload,
			// add the session collection as well
			if (!addedSessionCollection && this.sessionPayloads[anAdobeCode])
			{
				var aPayloadCollection = new Object;
				aPayloadCollection.payload = aPayload;
				aPayloadCollection.collection = this.sessionCollection;

				if (!this.sessionCollection.payloadRecords)
					this.sessionCollection.payloadRecords = new Object;
				this.sessionCollection.payloadRecords[anAdobeCode] = aPayloadCollection;

				aPayload.AddCollectionRecord(aPayloadCollection);
			}
		}
		
		// Dump the payload operation order so folks making multi-disk media can 
		// know the constraints
		try
		{
			this.orderedSessionPayloads = PayloadDependencySort(this.sessionPayloads);
			this.LogDebug("Operation order summary:\nWhen distributing payloads across media, the following order must be preserved,except that\nadjacent payloads with the same mediaGroup can be re-ordered across media boundaries without introducing\nextraneous media swaps for the user.")
			var lastLevel = "0,0";
			var mediaGroup = 0;
			thisCB = this;
			LogPayloadSet(this, "Operation order for all session payloads: mediaGroup (requires,satisfies)", this.orderedSessionPayloads,
				function(p)
				{
					var thisLevel = p.GetDependentsArray().length + "," + p.GetSatisfiedArray().length;
					if (thisLevel != lastLevel)
						mediaGroup++;
	
					lastLevel = thisLevel;
					return  mediaGroup  + " (" + thisLevel + ")" ;
				});
		}
		catch(ex)
		{
			this.LogError("Exception: " + ex);
		}

	//	this.LogDebug("this.allCollections");
	//	this.LogDebug(this.allPayloads);
	

	}
	catch (ex)
	{
		this.sessionErrorMessages.push(ex);
			
		var logError = "";
		if (ex[0])
		{
			logError = ex[0];
		}
		if (ex[1])
		{
			if (logError.length > 0)
			{
				logError += " - ";	
			}
			logError += ex[1];
		}
		this.LogError("Exception: " + logError);
		sessionResolved = false;
	}
	// Tell the container what happened
	this.SetSessionInitialized((doBootstrapUninstallCheck || sessionResolved) ? 1 : 0);
	return sessionResolved;
}

/**
Utility method to determine if a payload install/repair/remove operation is successful
@param	inStatusCode	Payload operation message.code value
*/
InstallerSession.prototype.IsOperationCodeSuccess = function(inStatusCode)
{
	var isSuccess = false;	
	if ((inStatusCode != null)&&
		(inStatusCode == gConstants.kORSuccess ||
		inStatusCode == gConstants.kORSuccessWithReboot ||
		inStatusCode == gConstants.kORSuccessWithMessage))
	{
		isSuccess = true;
	}
	return isSuccess;
}

/**
Utility method to look into the crystal ball and see whether or
not the specified payload will be installed on the user's machine
if the existing set of install actions were invoked
@param inPayload the payload to test
@retval true were installation to occur, the payload would be resident afterward
@retval false were installation to occur, the payload would not be resident afterward
*/
InstallerSession.prototype.WillPayloadBeResidentPostInstall = function(inPayload)
{
	var willBeResident = false;
	
	// if the payload is either installed now or marked for installation
	if ((inPayload.GetInstallationRefCount() > 0)
		|| (kInstallerActionInstall == inPayload.GetInstallerAction()))
	{
		// then it will be resident unless there's an upgrade
		// that is/will replace it
		var willBeUpgraded = false;
		
		var upgradingPayloadsMap = inPayload.GetPayloadsToUpgradeTo();
		for (var anUpgradingAdobeCode in upgradingPayloadsMap)
		{
			var anUpgradingPayload = upgradingPayloadsMap[anUpgradingAdobeCode];
			willBeUpgraded = this.WillPayloadBeResidentPostInstall(anUpgradingPayload);
			if (willBeUpgraded)
				break;
		}
		willBeResident = !willBeUpgraded;
	}
	
	return willBeResident;
}


/**
Utility method to look into the crystal ball and see what conflicts
would exist on the user's machine if the current set of install
actions were to be performed. The result is an array of conflict pairs where
the first element is the session InstallerPayload having the conflict and the
second element is the InstallerPayload with which it conflicts.
@return Array of conflict pairs that would exist if the install actions were performed
*/
InstallerSession.prototype.AccumulatePostInstallConflicts = function()
{
	var allFoundConflictPairs = new Array;
	
	for (var sessionPayloadCode in this.sessionPayloads)
	{
		var aSessionPayload = this.sessionPayloads[sessionPayloadCode];
		if (this.WillPayloadBeResidentPostInstall(aSessionPayload))
		{
			var conflictingPayloadMap = aSessionPayload.GetConflictingPayloads();
			for (var aConflictingAdobeCode in conflictingPayloadMap)
			{
				var aConflictingPayload = conflictingPayloadMap[aConflictingAdobeCode];
				if (this.WillPayloadBeResidentPostInstall(aConflictingPayload))
				{
					allFoundConflictPairs.push(new Array(aSessionPayload, aConflictingPayload));
				}
			}
		}
	}
	
	return allFoundConflictPairs;
}


/**
Returns an array of dependencies for payloads in this session
that would not be met if the current install choices were 'installed.'
@return Array of unmet dependency instances
*/
InstallerSession.prototype.AccumulateUnsatisfiedDependencies = function()
{
	// allUnmetDependencies will be an array of dependencies
	// instances that weren't met
	var allUnsatisfiedDependencies = new Array;
	
	// collect the dependencies
	var allInstallingDependencies = new Array;
	for (var sessionPayloadCode in this.sessionPayloads)
	{
		var aSessionPayload = this.sessionPayloads[sessionPayloadCode];
		var futureInstallState = this.GetPayloadPostInstallStateForSession(aSessionPayload);
		if (kCapsInstallStateInstalled == futureInstallState)
		{
			var payloadDependencies = aSessionPayload.GetUnresolvedDependencies();
			allInstallingDependencies = allInstallingDependencies.concat(payloadDependencies);
		}
	}
	
	// for each one, see if it's satisfied
	for (var dependencyIndex = 0; dependencyIndex < allInstallingDependencies.length; ++dependencyIndex)
	{
		var curDependency = allInstallingDependencies[dependencyIndex];
		var satisfied = false;
		if (null != curDependency.satisfyingPayloads)
		{
			for (var aPayloadCode in curDependency.satisfyingPayloads)
			{
				var aPayload = curDependency.satisfyingPayloads[aPayloadCode];
				var futureInstallState = this.GetPayloadPostInstallStateForSession(aPayload);
				satisfied = (kCapsInstallStateInstalled == futureInstallState);
				
				//Allow the user to uninstall a payload that had failed dependencies
				if(this.workflowMode == kWorkflowModeUninstall && futureInstallState == 0 && !(aPayload._installedStatus.logicallyInstalled || aPayload._installedStatus.physicallyInstalled))
				{
					satisfied = true;
				}
				
				if (satisfied)
					break;
			}
		}
		
		if (false == satisfied)
		{
			var bx64Exception = false;
			for (var testAdobeCode in this.x64ExceptionPayloads)
			{
				var testPayload = this.x64ExceptionPayloads[testAdobeCode];
				if (testPayload.SatisfiesDependency(curDependency))
				{
					bx64Exception = true;
					break;
				}
			}
			
			if(!bx64Exception)
				allUnsatisfiedDependencies.push(curDependency);

		}
	}
	
	return allUnsatisfiedDependencies;
}


/**
Returns the future logical install state of the specified payload
with respect to this session. This does not return whether or not
the payload will be physically installed, but instead returns
whether or not it will be 'in use' by this session.
@param inPayload the payload to determine future install state for
@retval true the payload will be 'installed' by the session post-install
@retval false the payload will not be installed for this session post-install
*/
InstallerSession.prototype.GetPayloadPostInstallStateForSession = function(inPayload)
{
	var futureInstallState = kCapsInstallStateUninstalled;
	
	var curInstallState = inPayload.GetInstallStateForCollection(this.sessionCollection);
	var installerAction = inPayload.GetInstallerAction();
	if (null == installerAction)
		installerAction = kInstallerActionNone;
	
	switch (installerAction)
	{
		case kInstallerActionNone :
		{
			if (null != curInstallState)
				futureInstallState = curInstallState;
		}
		break;
		
		case kInstallerActionRepair :
		case kInstallerActionInstall :
		{
			futureInstallState = kCapsInstallStateInstalled;
		}
		break;
		
		case kInstallerActionRemove :
		{
			futureInstallState = kCapsInstallStateUninstalled;
		}
		break;
	}
	
	return futureInstallState;
}

/**
Determine if the session is in install, maintenance, uninstall mode,
@retval install,
@retval maintenance,
@retval uninstall.
*/
InstallerSession.prototype.getWorkflowMode = function ()
{	
	if(this.workflowMode)
		return this.workflowMode;

	if(this.IsUninstallMode())
	{
	    this.workflowMode=kWorkflowModeUninstall;
		return kWorkflowModeUninstall;
	}
	else if(this.IsMaintenanceMode())
	{
		this.workflowMode=kWorkflowModeMaintenance;
		return kWorkflowModeMaintenance;
	}
	else
	{
	    this.workflowMode=kWorkflowModeInstall;
		return kWorkflowModeInstall;
	}
}


/**
Determine if the session is in maintenance mode.  
@retval true at least one payload from this session is installed, go to the maintenance workflow
@retval false no payloads from this session are installed, go to install workflow
*/
InstallerSession.prototype.IsMaintenanceMode = function()
{
	// 1. Short circuit if suppress uninstall is set on the driver payload
	var driver = this.GetDriverPayload();
	if (driver && driver.suppressUninstaller == 1)
	{
		this.LogInfo("Uninstall suppressed by driver payload");
		return false;
	}
	
	// 2. See if this collection has any installed payloads
	var myCollection = this.sessionData.key;
	for (var adobeCode in this.capsMap.Payloads)
	{
		var payload = this.capsMap.Payloads[adobeCode];
		for (var c = 0; c < payload.Collections.length; c++)
		{
			if (payload.Collections[c].collectionID == myCollection)
			{
				var state = payload.Collections[c].installState;
				if (kCapsInstallStateInstalling == state || kCapsInstallStateInstalled == state)
				{
					this.LogInfo("The collection has installed payloads.");
					return true;
				}
			}
		}
	}
	return false;
}

/**
Determine if the session is in uninstall mode.  
@retval true accordingly
@retval false accordingly
*/
InstallerSession.prototype.IsUninstallMode = function()
{
    var result = false;
    if (this.IsMaintenanceMode()) //Product has already been installed
        {
            var commandLineArgs = this.commandLineArgs;

            //If product is already installed and uninstall property = 1
            if (commandLineArgs && commandLineArgs.Properties && commandLineArgs.Properties.uninstall && commandLineArgs.Properties.uninstall == '1')
            {
                result = true;
            }
        }
    return result;
}

/**
If this session has been properly bootstrapped, there should be a collection
record in CAPS.  This method checks that.
*/
InstallerSession.prototype.IsBootstrapped = function()
{
	return this.GetSessionData().key
		&& this.capsMap
		&& this.capsMap.Collections
		&& this.capsMap.Collections[this.GetSessionData().key];
}


/**
Estimate the total disk space impact of the currently marked payload operations.
This is simply an accumulation of InstallerPayload.OperationSize() for the session
payloads.  The returned structure is the same.
*/
InstallerSession.prototype.OperationSize = function(inIgnoreMachineState)
{
	var result = {
		totalBytes: 0,
		roots: {}
	}

	for (var anAdobeCode in this.sessionPayloads)
	{
		var opSize = this.sessionPayloads[anAdobeCode].OperationSize(inIgnoreMachineState);
		result.totalBytes += opSize.totalBytes;
		for (var eachRoot in opSize.roots)
		{
			if (result.roots[eachRoot])
				result.roots[eachRoot] += opSize.roots[eachRoot];
			else
				result.roots[eachRoot] = opSize.roots[eachRoot];
		}		
	}
	
	return result;
}


/**
Begins installing, removing, repairing, and upgrading payloads
as described by their install actions.
@param inCallbackMethod method to receive status messages during installation
*/
InstallerSession.prototype.StartPayloadOperations = function(inStatusCallback, inCancelCallback)
{
	// store session properties in CAPS
	if (this.sessionCollection
		&& this.sessionCollection.collectionID)
	{
		this.StoreCollectionProperties(this.sessionCollection.collectionID, this.properties);
	}
	else
	{
		this.LogError("Unable to store session properties because the collection ID cannot be found.");
	}
	
	
	// Simulate
	/*
	try
	{
		_simulatePayloadOperations(this);
		// Dump the results
		for (var anAdobeCode in this.sessionPayloads)
		{
			var aPayload = this.sessionPayloads[anAdobeCode];
			this.LogDebug("Simulation results: " + aPayload);
			this.LogDebug(aPayload.GetOperationResult().currentStatus);
		}		
	}
	catch (ex)
	{
		window.alert("error:"  +ex);
		
	}
	finally
	{
		window.alert("quit now");
	}

	*/

	// change pages

	// Start the payloads
	_doPayloadOperations(this, inStatusCallback, inCancelCallback);
}


/**
Initialize the session payload selection policy nodes.
*/
InstallerSession.prototype.PayloadPolicyInit = function(inOptInstallerMode)
{
	// Short circuit if we have already calculated this for this mode.
	if (null != this._PayloadPolicyInitMode
		&& (this._PayloadPolicyInitMode == inOptInstallerMode
			|| this._PayloadPolicyInitMode == kWorkflowModeInstall && null == inOptInstallerMode))
	{
		return;
	}

	// Session payloads in dependency order
	var sessionPayloads = PayloadDependencySort(this.sessionPayloads, inOptInstallerMode == kWorkflowModeUninstall);
	var ac = null;

	// Performance fix: Get the installed state for all payloads in the session at one go
	// instead of each payload asking for its own in its constructor
	this.LogDebug("PayloadPolicyInit: BEGIN Updating installstate for payloads");
	var allSessionPayloadsAdobeCodesString = "";
	var allSessionPayloadsAdobeCodesArray = new Array();
	for (ac in sessionPayloads)
	{
	    allSessionPayloadsAdobeCodesArray[ac] = sessionPayloads[ac].GetAdobeCode();
	}
	allSessionPayloadsAdobeCodesString = allSessionPayloadsAdobeCodesArray.join(",");
	
	var sessionPayloadsInstallState = this.GetPayloadsPhysicalInstallState(allSessionPayloadsAdobeCodesString);
	
	// We are assuming that the GetPayloadsPhysicalInstallState call return payloads in the order we asked for them
	for (ac in sessionPayloads)
	{
	    sessionPayloads[ac]._installedStatus = sessionPayloadsInstallState.payloads[ac];
	}
	this.LogDebug("PayloadPolicyInit: END Updating installstate for payloads");

	// First pass, instantiate objects, defaulting to FN
	this.LogDebug("PayloadPolicyInit: BEGIN Creating policyNodes");
	for (ac in sessionPayloads)
	{
		var p = sessionPayloads[ac];
		p.policyNode = new PayloadPolicyNode(this, p);
	}
	this.LogDebug("PayloadPolicyInit: END Creating policyNodes");

	// Second pass, calculate the initial constraint and action states
	this.LogDebug("PayloadPolicyInit: BEGIN Calculating initial graph");
	for (ac in sessionPayloads)
	{
		var p = sessionPayloads[ac];
		p.policyNode.Init(inOptInstallerMode);
	}
	
	this._PayloadPolicyInitMode = inOptInstallerMode;
	
	this.LogDebug("PayloadPolicyInit: END Calculating initial graph");
}


/**
Refresh the session payload policy.  Call this on a change to any of:
  - install language
  - installer mode
  - serialization
*/
InstallerSession.prototype.PayloadPolicyRefresh = function(inOptInstallerMode)
{
	var sessionPayloads = PayloadDependencySort(this.sessionPayloads, inOptInstallerMode == kWorkflowModeUninstall);
	var ac = null;

	this.LogDebug("PayloadPolicyRefresh: BEGIN Calculating new payload policy graph");
	for (ac in sessionPayloads)
	{
		var p = sessionPayloads[ac];
		p.policyNode.Recompute(inOptInstallerMode);
	}
	this.LogDebug("PayloadPolicyRefresh: END Calculating new payload policy graph");
}

/**
Set Suite mode 
*/
InstallerSession.prototype.SetSuiteMode = function()
{
	this.LogDebug("Installer running in Suite mode");
    this._suiteMode = true;
}

/**
Are we running in Suite mode?
*/
InstallerSession.prototype.IsSuiteMode = function()
{
    if((this._suiteMode) && (this._suiteMode == true))
        return true;
    else
        return false;
}
