/*!
**********************************************************************
@file complete.js

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

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

/**
Implement a Wizard Page in three easy steps:

 1. Subclass WizardPage
 2. Extend with page-specific method overrides
 3. Return the WizardPage subclass name

*/

/***********************************************************************
1. Subclass WizardPage
*/
function complete_wp(inController)
{
	this.SetController(inController);
	this.restartNeeded = false;
}

complete_wp.prototype = new WizardPage("complete");

/***********************************************************************
2. Extend/override with page-specific logic
*/

complete_wp.prototype.GetDisplayName = function()
{
	return this.localization.GetString("locNavTitle", "Finish");
}


complete_wp.prototype.onResourcesLoaded = function()
{
	this.pageTitleText = new AdobeProperty();
	var pageTitleElement = this.getElementById("locPageTitle");
	if (pageTitleElement)
		this.pageTitleText.Bind(pageTitleElement);
	
	this.contentBox = this.getElementById("installFinishScrollPort");
}


complete_wp.prototype.onShow = function()
{
	this.setWindowTitle();
	this.wizardControl.session.UISetCloseBoxEnabled(0);	
	
	// Set the buttons
	this.wizardControl.quitButton.Hide();
	this.wizardControl.backButton.Hide();
	this.wizardControl.nextButton.SetLabel(this.localization.GetString("locNextButton", "Finish"));
	this.wizardControl.nextButton.SetFocus();
	this.wizardControl.nextButton.SetAccessKey("f");

	this.wizardControl.SetFocus(this.wizardControl.nextButton.button);

	// Set the title
	var operation = "";
	switch (this.wizardControl.setupMode)
	{
		case kInstallerModeRemove:
			operation = this.localization.GetString("locOperationRemove", "Uninstall");
			this.pageTitleText.Set(this.localization.GetString("locPageTitleRemove"));
			break;
		case kInstallerModeModify:
			operation = this.localization.GetString("locOperationModify", "Modify");
			this.pageTitleText.Set(this.localization.GetString("locPageTitleRepair"));
			break;
		default:
			operation = this.localization.GetString("locOperationInstall", "Install");
			this.pageTitleText.Set(this.localization.GetString("locPageTitleInstall"));
			break;
	}
	
	// Locate where to put the instruction text
	var pageInstructionElement = this.getElementById("locPageInstructions");

	// If we are in record mode, just collect the payload selections, save the result and be done.
	if (this.wizardControl.session.IsRecordMode())
	{
		var payloadDict = new Object();
		for (var payloadAdobeCode in this.wizardControl.session.sessionPayloads)
		{
			// Record only the driver and visible and checked payloads.
			var payload = this.wizardControl.session.sessionPayloads[payloadAdobeCode];
			var policy = payload.policyNode.GetUIPolicy();
			if ((policy.visible && policy.checkedState) || payload.IsDriverForSession(this.wizardControl.session))
			{
				payloadDict[payloadAdobeCode] = 1;
			}
		}

		var results = this.wizardControl.session.SaveDeploymentFiles(this.wizardControl.session.properties, payloadDict);
		this.wizardControl.session.LogInfo("Results of saving deployment files");
		this.wizardControl.session.LogInfo(results);
		
		// Show the user the results
		if (results && (results.installFile || results.removeFile))
		{
			this.AddTitle("Saved deployment files");

			if (results && results.installFile)
			{
				var p = this.AppendTextElement("p", "");
				this.AppendTextElement("strong", "Install: ", p);
				this.AppendTextElement("span", results.installFile, p);
			}

			if (results && results.removeFile)
			{
				var p = this.AppendTextElement("p", "");
				this.AppendTextElement("strong", "Remove: ", p);
				this.AppendTextElement("span", results.removeFile, p);
			}
		}
		else
		{
			this.AppendTextElement("h4", "Error saving deployment files");
		}

		// Short circuit return right here!
		return;
	}
	
	// Get the scoop on the payloads.
	var allPayloads = this.GetPayloadList();

	// Do we need a restart to keep anyone happy?
	if (true == this.restartNeeded || this.wizardControl.session.IsRestartNeeded())
	{
		this.restartNeeded = true; // Needed in onNext() pass the right exit code
		this.wizardControl.nextButton.SetLabel(this.localization.GetString("locFinishAndRestartButton", "Finish & Restart"));
		this.wizardControl.nextButton.SetAccessKey("r");

		this.wizardControl.backButton.SetLabel(this.localization.GetString("locNextButton", "Finish"));
		this.wizardControl.backButton.Show();
		this.wizardControl.backButton.SetAccessKey("f");

		var buttonTextMap = {
			Restart: this.localization.GetString("locFinishAndRestartButton", "Finish & Restart"),
			Finish: this.localization.GetString("locNextButton", "Finish")
		}
		this.errorbox.AddError("complete.restart", "warning", 
			this.localization.GetString("locFinishRestartWarningMessage", "Restarting your computer is recommended.  Click '[Restart]' to exit the install and restart or click '[Finish]' to exit immediately.", buttonTextMap));

		// Log the restart info for secondary use
		gSession.LogInfo(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");		
		gSession.LogInfo("Restarting your computer is recommended:");
		gSession.LogInfo("In order to complete the installation, please restart the computer");
		gSession.LogInfo(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
	}

	// Only if we are installing OR we have payload errors do we show the full report.
	if (this.wizardControl.setupMode == kInstallerModeInstall || 
		(allPayloads.fail.visibleList.length > 0) ||
		(allPayloads.fail.hiddenList.length > 0) ||
		(allPayloads.pass.messageCount > 0))
	{
		// Setup the section headers
		if (this.wizardControl.setupMode == kInstallerModeRemove)
		{
			allPayloads.pass.label = "locSectionRemove";
		}
		else
		{
			allPayloads.pass.label = "locSectionInstall";
		}
		allPayloads.pass.listClass = "alertSuccess";
		allPayloads.fail.label = "locSectionError";
		allPayloads.fail.listClass = "alertFailed";

		// Show the per-payload results.
		for (var payloadSet in allPayloads)
		{
			var set = allPayloads[payloadSet];
			if (set.visibleList.length > 0 || set.hiddenList.length > 0)
			{
				// Setup the section header and list
				var componentCount = set.visibleList.length;
				if (set.hiddenList.length > 0)
					componentCount++;
				if (set.label)
					this.AddTitle(this.localization.GetString(set.label, "", { ComponentCount: componentCount }));
				var listElement = this.AppendTextElement("ul", "");
				listElement.className = set.listClass;

				// List out the visible payloads
				for (var i = 0; i < set.visibleList.length; i++)
				{
					var name = set.visibleList[i].payloadName;
					var li = document.createElement("li");
					li.className = "completePayload";
					listElement.appendChild(li);
					var lip = this.AppendTextElement("p", name, li);
					lip.className = "productName";

					var opresult = this._textForOperationResult(set.visibleList[i].payloadOperation, set.visibleList[i].payloadResult);
					if (set.visibleList[i].payloadNote)
					{
						var span = this.AppendTextElement("span", "(" + set.visibleList[i].payloadNote.Translate(this.wizardControl.session.localization) + ")", lip);
						span.className = "payloadNote";
					}

					if (set.visibleList[i].payloadDetail || (opresult && opresult.detail))
					{
						if (opresult&& opresult.detail)
						{
							li.appendChild(this._createErrorListElement(null, opresult.detail))
						}
						if (set.visibleList[i].payloadDetail)
						{
							li.appendChild(this._createErrorListElement(null, set.visibleList[i].payloadDetail));
						}
					}
				}

				// Roll up shared component messages into a pseudo-single component.
				if (set.hiddenList.length > 0)
				{
					var li = document.createElement("li");
					li.className = "completePayload";
					listElement.appendChild(li);
					var lip = this.AppendTextElement("p", this.wizardControl.session.localization.GetString("locHiddenPayloadsUC"), li);
					lip.className = "productName";
					
					// A map to accumulate the unique messages
					var detailMessages = new Object();
					var detailCount = 0;

					// Collect the details
					for (var i = 0; i < set.hiddenList.length; i++)
					{
						var opresult = this._textForOperationResult(set.hiddenList[i].payloadOperation, set.hiddenList[i].payloadResult);
						if (opresult && opresult.detail)
						{
							detailMessages[opresult.detail] = true;
							detailCount++;
						}
					}

					// Show the details
					if (detailCount > 0)
					{
						for (var detailMessage in detailMessages)
						{
							li.appendChild(this._createErrorListElement(null, detailMessage));
						}
					}
				}
			}
		}

		// Setup the page instruction block.
		if (allPayloads.fail && allPayloads.fail.visibleList.length > 0)
		{
			var errorText = this.localization.GetString("locDoneWithErrorsInstall");
			if (this.wizardControl.setupMode == kInstallerModeRemove)
				errorText = this.localization.GetString("locDoneWithErrorsRemove");
			pageInstructionElement.innerHTML = "<p><img src=\"media/img/iconWarning.png\" alt=\"\"/> " + errorText + "</p>";
		}
		else if (this.wizardControl.setupMode != kInstallerModeRemove)
		{
			pageInstructionElement.innerHTML = "<p>" 
				+ this.localization.GetString("locDoneFirstLaunch", "You will be asked to complete your product setup the first time you launch.")
				+ "</p>";
		}

		
	}
	else
	{
		// No errors and not installing, we obliterate the summary scrollport and shove in a one-liner summary.
		var contentParent = this.contentBox.parentElement;
		contentParent.removeChild(this.contentBox);
		switch (this.wizardControl.setupMode)
		{
		 	case kInstallerModeRemove:
				this.AppendTextElement("h4", this.localization.GetString("locAllSuccessRemove", "All components were successfully removed."), pageInstructionElement);
				break;
			case kInstallerModeModify:
				this.AppendTextElement("h4", this.localization.GetString("locAllSuccessRepair", "All components were successfully installed or reinstalled."), pageInstructionElement);
				break;
		}	
	}
}


/**
Fabricate the DOM for a system check error/warning
*/
complete_wp.prototype._createErrorListElement = function(inClass, inText, inOptContainerElement)
{
	var session = this.wizardControl.session;

	var isArray = function(inObj)
	{
		return typeof inObj == "object" && inObj.length && inObj.concat && inObj.join;
	};

	var isLocalizedString = function(inObj)
	{
		return typeof inObj == "object" && inObj.Translate && typeof inObj.Translate == "function";
	};

	var resolveString = function(inObj, forLog)
	{
		if (isLocalizedString(inObj))
		{
			if (forLog)
				return inObj.Translate(session.localization, 'en_US');
			else
				return inObj.Translate(session.localization);
		}
		return inObj;
	};

	var contentList = inText;
	if (!isArray(inText))
		contentList = new Array(inText);
		
	var errorDiv = document.createElement(typeof inOptContainerElement == "string" ? inOptContainerElement : "div");
	if (inClass)
		errorDiv.className = inClass;

	for (var i in contentList)
	{
		var item = contentList[i];
		if (isArray(item))
		{
			if (item.length > 0)
			{
				var listElement = document.createElement("ul");
				for (var si in item)
				{
					var li = document.createElement("li");
					li.appendChild(document.createTextNode(resolveString(item[si])));
					listElement.appendChild(li);
				}
				errorDiv.appendChild(listElement);
			}
		}
		else
		{
			var p = document.createElement("p");
			p.appendChild(document.createTextNode(resolveString(item)));
			errorDiv.appendChild(p);
		}
	}

	return errorDiv;
}


/**
For an payload operation and the companion result, come up with the UI text.
*/
complete_wp.prototype._textForOperationResult = function(inOperation, inOperationResult)
{
	var result = {
		text: null,
		detail: null,
		alert: true
	};

	if (inOperationResult && inOperationResult.message)
	{
		if (inOperationResult.message.code == gConstants.kORSuccess
			|| inOperationResult.message.code == gConstants.kORSuccessWithReboot 
			|| inOperationResult.message.code == gConstants.kORSuccessWithMessage)
		{
			switch (inOperation)
			{
				case kInstallerActionInstall:
					result.text = this.localization.GetString("locSuccessInstalled", "Installed");
					break;
				case kInstallerActionRepair:
					result.text = this.localization.GetString("locSuccessRepaired", "Reinstalled");
					break;
				case kInstallerActionRemove:
					result.text = this.localization.GetString("locSuccessRemoved", "Removed");
					break;
			}
			
			if (inOperationResult.message.code == gConstants.kORSuccessWithMessage)
			{		
				if (inOperationResult.message.args)
				{
					result.detail = inOperationResult.message.args[getUserInterfaceLanguage(this.wizardControl.session)];
					if (null == result.detail)
					{
						result.detail = inOperationResult.message.args["en_US"];
					}					
				}
				result.alert = false;
			}
		}
		else
		{			
			switch (inOperation)
			{
				case kInstallerActionInstall:
					result.text = this.localization.GetString("locFailInstalled", "Not installed");
					break;
				case kInstallerActionRepair:
					result.text = this.localization.GetString("locFailRepaired", "Not reinstalled");
					break;
				case kInstallerActionRemove:
					result.text = this.localization.GetString("locFailRemoved", "Not removed");
					break;
			}
			switch (Number(inOperationResult.message.code))
			{
				case gConstants.kORUserCancel:
					result.detail = (kInstallerActionRemove != inOperation) ? 
					 				this.localization.GetString("locErrorUserCancel", "User canceled installation") :
									this.localization.GetString("locErrorUninstallUserCancel", "User canceled uninstallation");
					break;
				case gConstants.kORConflictsExist:
					result.detail = this.localization.GetString("locErrorConflicts", "Conflicts with a component already installed");
					break;
				case gConstants.kORUpgradeFailure:
					result.detail = this.localization.GetString("locErrorUpgradeFailure", "Upgrade failed");
					break;
				case gConstants.kORMissingMedia:
					result.detail = this.localization.GetString("locErrorFailedMissingMedia", "Install failed - missing media", inOperationResult.message.args);
					break;			
				default:
					result.detail = (kInstallerActionRemove != inOperation) ? 
				 					this.localization.GetString("locErrorFailed", "Install failed") :
									this.localization.GetString("locErrorUninstallFailed", "Uninstall failed");
					break;
			}
		}
	}
	return result;
}


complete_wp.prototype.onNext = function()
{
	if (true == this.restartNeeded)
		this.wizardControl.session.UIExitDialog('8');
	else
		this.wizardControl.session.UIExitDialog();
}

complete_wp.prototype.onCancel = function()
{
	// No-op for the complete screen
}


// The reworked Back is Finish in cases where a restart is optional
complete_wp.prototype.onBack = function()
{
	this.wizardControl.session.UIExitDialog();
}


/**
Calculate what we need to show for the current session.
*/
complete_wp.prototype.GetPayloadList = function(inAction, inVisible)
{
	var result = {
		pass: {
			visibleList: [],
			hiddenList: [],
			messageCount: 0
		},
		fail: {
			visibleList: [],
			hiddenList: [],
			messageCount: 0
		}
	};

	var session = this.wizardControl.session;

	// This really, really doesn't belong here, but the correct place only
	// exists in a future refactored complete.js.
	var uninstallMethods = new Array();
	uninstallMethods.push(new LocalizedString("locRemoveMethodOriginal", "Launch its original installer"));
	if (this.wizardControl.session.properties["platform"] == "OSX")
		uninstallMethods.push(new LocalizedString("locRemoveMethodOSX", "Use the Uninstall Utility in [installerPath]", {installerPath: "/Applications/Utilities/Adobe Installers"}));
	if (this.wizardControl.session.properties["platform"] == "Win32")
		uninstallMethods.push(new LocalizedString("locRemoveMethodWin32", "Use the Add/Remove Programs Utility"))

	// Get a proper UI sort
	var sessionPayloads = PayloadUISort(session.sessionPayloads, session);

	for (adobeCode in sessionPayloads)
	{
		var p = sessionPayloads[adobeCode];
		var uiInfo = p.GetUISelectionAction(session, this.wizardControl.setupMode);

		// Pick a list based on the operation result
		var operationResult = p.GetOperationResult();
		var success = (operationResult 
			&& operationResult.message
			&& (operationResult.message.code == gConstants.kORSuccess
		 		|| operationResult.message.code == gConstants.kORSuccessWithReboot 
				|| operationResult.message.code == gConstants.kORSuccessWithMessage));
		var list = operationResult ? (success ? result.pass : result.fail) : null;

		if (list)
		{
			// Formulate the UI text
			var uitext = {
				payloadOperation: p.GetInstallerAction(),
				payloadName: p.GetUIProductName(session),
				payloadNote: (ContainerNotEmpty(p.GetPayloadsToUpgradeFrom()) && p.GetInstallerAction() == kInstallerActionInstall) ? uiInfo.payloadNote : null,
				payloadDetail: null,
				payloadResult: operationResult
			}

			// Flag if this payload needs a restart
			if (operationResult.message
				&& operationResult.message.code == gConstants.kORSuccessWithReboot)
			{
				this.restartNeeded = true;
			}

			// Are we a de-refcount?
			var installState = session.GetPayloadPhysicalInstallState(p.GetAdobeCode());
			if (success && p.GetInstallerAction() == kInstallerActionRemove
				&& installState && installState.physicallyInstalled != "0")
			{
				if (p.policyNode.isSessionDriver)
				{
					list.messageCount++;
					uitext.payloadDetail = [
						new LocalizedString("locToCompletelyRemoveDo", "To completely remove this software do one of the following:"),
						uninstallMethods
					];
				}
				else if (p.policyNode.visible)
				{
					list.messageCount++;
					uitext.payloadDetail = [
						new LocalizedString("locDeRefcountVisible", "[payloadName] remains on your computer because a different installer originally installed it.", { payloadName: p.GetUIProductName(session) }),
					 	new LocalizedString("locToRemoveDo"),
						uninstallMethods
					];
				}
				else
				{
					uitext.payloadDetail = new LocalizedString("locDeRefcountHidden", "Some components remain on your computer because they are in use by other Adobe products.");
				}

			}

			// Pick a sublist based on visibility and checked state.
			if (uiInfo.visible || p.IsDriverForSession(session))
			{
				if (uiInfo.checkedState)
				{
					list.visibleList.push(uitext);
					if (operationResult.message.code == gConstants.kORSuccessWithMessage)
						list.messageCount += 1;
				}
			}
			else
			{
				list.hiddenList.push(uitext);
			}
		}
	}

	return result;
}


complete_wp.prototype.AddTitle = function(inTitle)
{
	return this.AppendTextElement("h4", inTitle + ":");
}


complete_wp.prototype.AppendTextElement = function(inElementName, inText, inContainer)
{
	var container = this.contentBox;
	if (arguments.length == 3)
		container = inContainer

	if (container)
	{
		var e = document.createElement(inElementName);
		e.appendChild(document.createTextNode(inText));
		container.appendChild(e);
		return e;
	}
	return null;
}



/***********************************************************************
3. Last, and very important, return the name of the class.
*/
"complete_wp";
