/***********************************************************************/
/*                                                                     */
/*                      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 MultiWorkflowStorage(/*[Array]*/ inWorkflowBasePaths, /*[String]*/ inBaseURL, /*[String]*/ inCacheBasePath)
{
	var localStorage = [];
	var remoteStorage = ((isValidProperty(inBaseURL) && inBaseURL.length) ? new RemoteWorkflowStorage(inCacheBasePath, inBaseURL) : null);
 
	//////////////////////////////////////////////////////////////////////////////
	//
	// Return an array consisting of workflows
	//
	this.getWorkflows = function(/*[Function]*/ inCallback)
	{
		throwInvalid(inCallback);

		var callback = inCallback;
		var workflows = [];
		
		forEach(localStorage, function(storage)
		{
			storage.getWorkflows(function(inWorkflows)
			{
				workflows = workflows.concat(inWorkflows);
			});
		});
		
		if(isValidProperty(remoteStorage))
		{
			remoteStorage.getWorkflows(function(inRWorkflows)
			{
				workflows = concatWorkflowLists(workflows, inRWorkflows);
				
				if (isValidProperty(callback))
				{
					callback(workflows);
				}
			});
		}
		else if (isValidProperty(callback))
		{
			callback(workflows);
		}
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Return only cached Workflows
	// The callback might be called twice:
	// 1. for already cached Workflows
	// 2. for Workflows which are downloaded and cached
	//
	this.getCachedWorkflows = function(/*[Function]*/ inCallback)
	{
		throwInvalid(inCallback);

		var callback = inCallback;
		var workflows = [];
		
		// concat array of local stored workflows
		//
		forEach(localStorage, function(storage)
		{
			storage.getWorkflows(function(inWorkflows)
			{
				workflows = workflows.concat(inWorkflows);
			});
		});
		
		// return local stored workflows
		//
		dbgLogWorkflows("MultiWorkflowStorage.getCachedWorkflows", "Local workflows", workflows);
		callback(workflows);

		// start download of remote Workflows
		//
		if(isValidProperty(remoteStorage))
		{
			remoteStorage.getWorkflows(function(inRWorkflows)
			{
				dbgLogWorkflows("MultiWorkflowStorage.getCachedWorkflows", "Remote workflows", inRWorkflows);

				workflows = concatWorkflowLists(workflows, inRWorkflows);

				dbgLogWorkflows("MultiWorkflowStorage.getCachedWorkflows", "Merged local and remote workflows", workflows);

				if (isValidProperty(callback))
				{
					callback(workflows);
				}
			});
		}
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Return Workflow object for the given workflow id inID
	//
	this.getWorkflow = function(/*[string]*/ inID, /*[Function]*/ inCallback)
	{
		throwInvalid(inCallback);

		var callback = inCallback;
		var ret = null;
		
		for (var index=0; index<localStorage.length && !isValidProperty(ret); index++)
		{
			localStorage[index].getWorkflow(inID, function(inWorkflow)
			{
				if (!isValidProperty(ret))
				{
					ret = inWorkflow;
				}
			});
		}
		
		if (!isValidProperty(ret) && isValidProperty(remoteStorage))
		{
			remoteStorage.getWorkflow(inID, function(inRWorkflow)
			{
				if (isValidProperty(callback))
				{
					dbgLogWorkflows("MultiWorkflowStorage.getWorkflow", "Remote workflow", [inRWorkflow]);
					callback(inRWorkflow);
				}
			});
		}
		else if (isValidProperty(callback))
		{
			dbgLogWorkflows("MultiWorkflowStorage.getWorkflow", "Local workflow", [ret]);
			callback(ret);
		}
	}
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Concat array with workflows
	// Leave duplicates out
	//
	function concatWorkflowLists(/*[Array]*/ inWorkflows1, /*[Array]*/ inWorkflows2)
	{
		var workflows = [];

		forEach(inWorkflows2, function(workflow)
		{
			var found = null;
			for (var i=0; i<inWorkflows1.length; i++)
			{
				if (workflow.id == inWorkflows1[i].id)
				{
					found = inWorkflows1[i];
					break;
				}
			}	
			
			if (found == null)
			{
				workflows.push(workflow);
			}					
		});
		
		return inWorkflows1.concat(workflows);
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Debug logging
	//
	function dbgLogWorkflows(/*[String]*/ inFunction, /*[String]*/ inText, /*[Array]*/ inWorkflows)
	{
		var idStr = '';

		forEach(inWorkflows, function(workflow)
		{
			if (isValidProperty(workflow))
			{
				if (isValidProperty(workflow.name))
				{
					idStr += workflow.name + ' ';
				}
				if (isValidProperty(workflow.id))
				{
					idStr += '[' + workflow.id + ']';
				}
			}
			idStr += ', ';
		});

		dbglog('(' + inFunction + ') ' + inText + ': ' + idStr);
	}
 
	function initialize()
	{
		forEach(inWorkflowBasePaths, function(path)
		{
			localStorage.push(new LocalWorkflowStorage(path));
		});
	}
	initialize();
}