/***********************************************************************/
/*                                                                     */
/*                      ADOBE CONFIDENTIAL                             */
/*                   _ _ _ _ _ _ _ _ _ _ _ _ _                         */
/*                                                                     */
/*  Copyright 2016 Adobe Systems Incorporated                          */
/*  All Rights Reserved.                                               */
/*                                                                     */
/* NOTICE:  All information contained herein is, and remains           */
/* the property of Adobe Systems Incorporated and its suppliers,       */
/* if any.  The intellectual and technical concepts contained          */
/* herein are proprietary to Adobe Systems Incorporated and its        */
/* suppliers and are protected by all applicable intellectual property */
/* laws, including trade secret and copyright laws.                    */
/* Dissemination of this information or reproduction of this material  */
/* is strictly forbidden unless prior written permission is obtained   */
/* from Adobe Systems Incorporated.                                    */
/*                                                                     */
/***********************************************************************/

function WorkflowDisplayAdapter(/*[PanelSurface]*/ inSurface, /*[Workflow]*/ inWorkflow)
{
	throwInvalid(inSurface);
	
	var workflow = inWorkflow;
	var surface = inSurface;
	var contentStorage = (isValidProperty(WorkflowDisplayAdapter.sContentStorage) ? WorkflowDisplayAdapter.sContentStorage : IContentStorage.create());
	var contentJobs = [];
	WorkflowDisplayAdapter.sContentStorage = contentStorage;
	
	throwInvalid(contentStorage);
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show selected workflow
	//
	this.showInitial = function()
	{
		hideStepIndicator();
		displayWorkflowContent();
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show next step of Workflow
	//
	this.showStep = function(/*[Number]*/ inStepNumber)
	{
		hideStepIndicator();
		displayWorkflowStepContent(inStepNumber);
		
		try
		{
			showStepIndicator(inStepNumber);
		}
		catch(exc)
		{
			exclog(exc);
		}
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show workflow step success
	//
	this.showStepSuccess = function(/*[Number]*/ inCurrentStep)
	{
		hideStepIndicator();
		displayWorkflowStepContent(inCurrentStep);
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show workflow step failure
	//
	this.showFailure = function(/*[Number]*/ inCurrentStep, /*[WorkflowContent]*/ inContentXtra)
	{
		hideStepIndicator();
		displayWorkflowStepContent(inCurrentStep, inContentXtra);
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show workflow processing success
	//
	this.showSuccess = function()
	{
		hideStepIndicator();
		displayWorkflowContent();
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show workflow processing canceled
	//
	this.showCancel = function()
	{
		hideStepIndicator();
		displayWorkflowContent();
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Show all workflow titles
	//
	this.showTitles = function(/*[String]*/ inLocatorID, /*[Array]*/ inWorkflows, /*[Function]*/ inClickHandler)
	{
		throwInvalid(inLocatorID);
		throwInvalid(inWorkflows, 'Array');

		cancelJobs();
		
		hideStepIndicator();

		var generatorJob = new CompoundJob();

		var locatorID = inLocatorID;
		var list = '';
		var count = inWorkflows.length;

		// display final list
		//
		function doDisplay()
		{
			display(inLocatorID, list);
		}

		for (var i=0; i<inWorkflows.length; i++)
		{
			// get content from workflow
			//
			var content = null;

			try
			{
				content = inWorkflows[i].getContent(CONTENTLOCATOR_WORKFLOW_LIST_TITLE);
			}
			catch (exc)
			{
				exclog(exc);
				content = null;
			}

			// generate html for content
			//
			if (content)
			{
				generatorJob.addJob(generateWorkflowHtml(inWorkflows[i], content, inClickHandler));
			}
			else
			{
				count--;
			}
		}

		// wait for each result and build up the final list for display
		//
		var colCount = 0;
		var kMaxColumns = 3;

		generatorJob.wait(function(/*[Array]*/ inContentHtml)
		{
			list = '';

			forEach(inContentHtml, function(/*[String]*/ inEntry)
			{
				if (colCount == 0)
				{
					list += '<div class="grid-common equalize">';
				}

				list += '<div class="grid-column s-grid-common cell-padded"><div class="cell-padded-inner content-box"><div id="workflowlistentry">';
				list += inEntry;
				list += '</div></div></div>';

				colCount++;

				if (colCount == kMaxColumns)
				{
					colCount = 0;
					list += '</div>';
				}
			});

			count -= inContentHtml.length;

			if (count == 0)
			{
				// insert one invisble extra cell to extend the vertical scroll aread
				//
				if (colCount == 0)
				{
					list += '<div class="grid-common equalize">';
				}

				list += '<div class="grid-column s-grid-common cell-padded"><div class="cell-padded-inner content-box"><div id="workflowlistentry">';
				list += '<p></p>';
				list += '</div></div></div>';

				colCount++;

				if (colCount == kMaxColumns)
				{
					colCount = 0;
					list += '</div>';
				}

				// display list
				//
				doDisplay();
			}
		},
		function(/*[Array]*/ inError)
		{
			count -= inError.length;
			if (count == 0)
			{
				doDisplay();
			}
		});

		return generatorJob;
	}
	
	// private ///////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Take all Workflow content locator id's and try to display them on the 
	// current surface.
	//
	function displayWorkflowContent()
	{
		if (isValidProperty(workflow))
		{
			cancelJobs();
			displayAllContent(workflow);
		}
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Take all Workflow step content locator id's and try to display them on the 
	// current surface.
	//
	function displayWorkflowStepContent(/*[Number]*/ inStepNumber, /*[WorkflowContent]*/ inContentXtra)
	{
		if (isValidProperty(workflow))
		{
			cancelJobs();
			var step = null;
			
			try
			{
				step = workflow.getStep(inStepNumber);
			}
			catch(exc)
			{
				exclog(exc);
				step = null;
			}
		
			if (step)
			{
				displayAllContent(step);
			}
			
			if (isValidProperty(inContentXtra))
			{
				displayAllContent(inContentXtra);
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Try to display all content of the content owner
	// inContentOwner could be of type Workflow, WorkflowStep, WorkflowContent
	//
	function displayAllContent(/*[Object]*/ inContentOwner)
	{
		throwInvalid(inContentOwner);
		throwInvalid(inContentOwner.getContentLocator);
		throwInvalid(inContentOwner.getContent);

		progress(true);

		var count = 0;
		var locators = null;

		try
		{
			locators = inContentOwner.getContentLocator();
		}
		catch(exc)
		{
			exclog(exc);
			locators = null;
		}

		throwInvalid(locators, 'Array');

		count = locators.length;

		// finalize job
		//
		function finalize(/*[IJob]*/ inJob)
		{
			if (--count <= 0)
			{
				progress(false);
			}

			finalizeJob(inJob);
		}

		// display one content part
		//
		function doDisplay(/*[Object]*/ inContentOwner, /*[String]*/ inLocator)
		{
			var locator = inLocator;
			var content = null;

			try
			{
				content = inContentOwner.getContent(locator);
			}
			catch(exc)
			{
				exclog(exc);
				content = null;
			}

			if (content)
			{
				var job = generateWorkflowHtml(workflow, content, null);
				contentJobs.push(job);

				job.wait(function (/*[String]*/ inContentHtml)
				{
					display(locator, inContentHtml);
					finalize(job);
				},
				function (/*[any]*/ inError)
				{
					finalize(job);
				});
			}
			else if (--count <= 0)
			{
				progress(false);
			}
		}

		// display all content parts
		//
		forEach(locators, function(locator)
		{
			doDisplay(inContentOwner, locator);
		});
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Generate HTML for workflow content
	//
	function generateWorkflowHtml(/*[Workflow]*/ inWorkflow, /*[WorkflowContent]*/ inContent, /*[Function]*/ inClickHandler)
	{
		var job = new Job();
		var ret = '';
		var workflow = inWorkflow;
		var workflowID = inWorkflow.id;
		var contentID = inContent.id;
		var mimeType = inContent.mimeType;
		var clickHandler = inClickHandler;

		function addClickHdl(/*[String]*/ inHTML)
		{
			var html = inHTML;

			if (isValidProperty(html) && html.length && isValidProperty(clickHandler))
			{
				html = '<a id="' + workflow.id + '" href="#" onclick="' + clickHandler.name + '(this.id);">' + html + '</a>';
			}

			return html;
		}

		switch(mimeType)
		{
			case 'text/html':
			{
				var generateJob = contentStorage.getRaw(workflowID, contentID);
				contentJobs.push(generateJob);
				generateJob.wait(function(/*[String]*/ inResult)
				{
					if (inResult.length)
					{
						var symbolJob = replaceWorkflowAllSymbols(inResult, contentStorage, workflowID);
						contentJobs.push(symbolJob);
						symbolJob.wait(function(/*[String]*/ inResult)
						{
							var html = addClickHdl(inResult);
							job.setResult(html);
						},
						function(/*[any]*/ inError)
						{
							job.setError("WorkflowDisplayAdapter.generateWorkflowHtml [" + workflowID + " / " + contentID + " / " + mimeType + "] FAILED");
							dbglogError(job.getError());
						});
					}
				},
				function(/*[any]*/ inError)
				{
					job.setError("WorkflowDisplayAdapter.generateWorkflowHtml [" + workflowID + " / " + contentID + " / " + mimeType + "] FAILED");
					dbglogError(job.getError());
				});
			}
			break;
			
			case 'text/plain':
			{
				var generateJob = contentStorage.getString(workflowID, contentID);
				contentJobs.push(generateJob);
				generateJob.wait(function(/*[String]*/ inResult)
				{
					if (inResult.length)
					{
						var symbolJob = replaceWorkflowAllSymbols(inResult, contentStorage, workflowID);
						contentJobs.push(symbolJob);
						symbolJob.wait(function(/*[String]*/ inResult)
						{
							var content = inResult;

							if (!isValidProperty(clickHandler))
							{
								content = generateHtml(content, mimeType);
							}

							content = addClickHdl(content);
							job.setResult(content);
						},
						function(/*[any]*/ inError)
						{
							job.setError("WorkflowDisplayAdapter.generateWorkflowHtml [" + workflowID + " / " + contentID + " / " + mimeType + "] FAILED");
							dbglogError(job.getError());
						});
					}
				},
				function(/*[any]*/ inError)
				{
					job.setError("WorkflowDisplayAdapter.generateWorkflowHtml [" + workflowID + " / " + contentID + " / " + mimeType + "] FAILED");
					dbglogError(job.getError());
				});
			}
			break;
			
			case 'audio/x-mpeg':
			case 'audio/x-wav':
			case 'image/gif':
			case 'image/jpeg':
			case 'image/png':
			case 'video/mp4':
			{
				var generateJob = contentStorage.getURL(workflowID, contentID);
				contentJobs.push(generateJob);
				generateJob.wait(function(/*[String]*/ inResult)
				{
					var content = generateHtml(inResult, mimeType);
					content = addClickHdl(content);
					job.setResult(content);
				},
				function(/*[any]*/ inError)
				{
					job.setError("WorkflowDisplayAdapter.generateWorkflowHtml [" + workflowID + " / " + contentID + " / " + mimeType + "] FAILED");
					dbglogError(job.getError());
				});
			}
			break;

			default:
			{
				job.setError("WorkflowDisplayAdapter.generateWorkflowHtml [" + workflowID + " / " + contentID + "] invalid mime type");
				dbglogError(job.getError());
			}
		}

		return job;
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Generate HTML for content
	//
	function generateHtml(/*[String]*/ inContent, /*[String]*/ inMimeType)
	{
		var ret = inContent;
		
		if (isValidProperty(ret))
		{
			switch(inMimeType)
			{
				case 'text/plain':
				{
					if (ret.length)
					{
						ret = '<p>' + ret + '</p>';
					}
				}
				break;
				case 'audio/x-mpeg':
				case 'audio/x-wav':
				{
					if (ret.length)
					{
						ret  = '<audio autoplay><source src="' + ret;
						ret += '" type="';
						ret += inMimeType;
						ret += '"></audio>';
					}
				}
				break;
				case 'image/gif':
				case 'image/jpeg':
				case 'image/png':
				{
					if (ret.length)
					{
						ret  = '<img src="' + ret;
						ret += '"/>';
					}
				}
				break;
				case 'video/mp4':
				{
					if (ret.length)
					{
						ret  = '<video autoplay loop><source src="' + ret;
						ret += '" type="';
						ret += inMimeType;
						ret += '"></video>';
					}
				}
				break;
			}
		}
				
		return ret;
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Show/Hide progress
	//
	function progress(/*[Boolean]*/ inVisible)
	{
		if (inVisible)
		{
			var snippet = '<img src="./surfaces/progress.gif">';
			surface.displayByID(CONTENTLOCATOR_PROGRESS, snippet);

		}
		else
		{
			surface.displayByID(CONTENTLOCATOR_PROGRESS, '');

		}
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Display content at locator ID
	//
	function display(/*[String]*/ inLocator, /*[String]*/ inContentHtml)
	{
		surface.displayByID(inLocator, inContentHtml);
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Show indicator overlay
	//
	function showStepIndicator(/*[Number]*/ inStepNumber)
	{
		if (isValidProperty(workflow))
		{
			var step = workflow.getStep(inStepNumber)
			throwInvalid(step, 'WorkflowStep');
			
			var indicator = step.getAllIndicator();
			throwInvalid(indicator, 'Array');
			
			for (var i=0; i<indicator.length; i++)
			{
				indicator[i].display(contentStorage);
			}
		}
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Hide indicator overlay
	//
	function hideStepIndicator()
	{
		if (isValidProperty(workflow))
		{
			for (var s=0; s<workflow.getStepLength(); s++)
			{
				var step = workflow.getStep(s)
				if (isValidProperty(step))
				{
					var indicator = step.getAllIndicator();
					if (isValidProperty(indicator, 'Array'))
					{
						for (var i = 0; i < indicator.length; i++)
						{
							indicator[i].cancelDisplay();
						}
					}
				}
			}
		}

		var job = new ScriptJob('hideAllIndicator();');
		job.wait(null, function(/*[String]*/ inError)
		{
			dbglogError(inError);
		});
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Cancel and cleanup all jobs
	//
	function cancelJobs()
	{
		while(contentJobs.length > 0)
		{
			contentJobs.pop().cancel();
		}
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Finalize Job and remove from list
	//
	function finalizeJob(/*[IJob]*/ inJob)
	{
		for (var i=0; i<contentJobs.length; i++)
		{
			if (contentJobs[i] == inJob)
			{
				contentJobs.splice(i, 1);
				break;
			}
		}
	}
}

// global content storage
//
WorkflowDisplayAdapter.sContentStorage = null;