text: /*
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at
  
        http://www.apache.org/licenses/LICENSE-2.0
  
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
  */
  
  // File Tree
  
  var _staging = '/';	// current root path in staging area browser
  var _catalog = '/';	// current root path in catalog browser
  var _paths   = { "staging" :  '/', 
                   "catalog" :  '/',
                   "currentStagedFile" : '',
                   "currentCatalogedFile" : '',
                   "currentProductType" : ''}
  
  if(jQuery) (function($){
  	
  	$.extend($.fn, {
  		fileTree: function(o, h, i) {
  			// Defaults
  			if( !o ) var o = {};
  			if( o.root == undefined ) o.root = '/';
  			if( o.folderEvent == undefined ) o.folderEvent = 'dblclick';
  			if( o.expandSpeed == undefined ) o.expandSpeed= 500;
  			if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
  			if( o.expandEasing == undefined ) o.expandEasing = null;
  			if( o.collapseEasing == undefined ) o.collapseEasing = null;
  			if( o.multiFolder == undefined ) o.multiFolder = true;
  			if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';
  			
  			// Understand which of the two browsers to apply nav actions to
  			if (o.which == undefined) { alert('please specify \'which\' (options are: "staging"|"catalog") '); o.which = "staging";}
  			
  			// Ensure a script has been provided
  			if (o.script == undefined) { alert('please specify a target script \'script\' in fileTree options'); }
  			
  			// Get a handle to the outer UL
  			o.outerContainer = '#' + $(this).attr('id');
  			if (o.outerContainer == undefined) { alert('container must have unique id') };
  			
  			$(this).each( function() {
  				
  				function showTree(c, t) {
  					$(c).addClass('wait');
  					$(".fileTree.start").remove();
  					$.get(o.script, { path: t }, function(data) {
  						$(c).find('.start').html('');
  						$(c).removeClass('wait').html(data);
  						if (o.which == "staging")
  							_paths.staging = escape(t);
  						else
  							_paths.catalog = escape(t);
  						bindTree(c);
  						updateNav(o.which);
  						clearMetadataWorkbenchContent(o.which);
  						initDraggables();
  					});
  				}
  				
  				function bindTree(t) {
  					$(o.outerContainer).find('UL LI A').bind('click', function() {
  						if ($(this).parent().hasClass('productType')) {
  							i($(this).attr('rel'));
  						} else if ($(this).parent().hasClass('file')) {
  							h($(this).attr('rel'));
  						}
  					}).bind('dblclick', function() {
  						if ($(this).parent().hasClass('directory') ) {
  							$(this).parent().find('UL').remove(); // cleanup
  							showTree( $(o.outerContainer), escape($(this).attr('rel')) );
  						}
  					});
  					
  					// Prevent A from triggering the # on non-click events
  					if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
  				}
  				
  				// Loading message
  				$(this).html('<ul class="fileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
  				
  				// Get the initial file list
  				showTree( $(this), escape((o.which == "staging" ) ? _paths.staging : _paths.catalog) );
  			});
  		}
  	});
  })(jQuery);
  
  // Metadata editors
  function makeStagedMetadataEditable() {
  	makeMetadataEditable(
  		$("#stagedMetadataWorkbenchContent > table > tbody > tr >  td"),
  		updateStagedMetadata);
  }
  
  function makeProductMetadataEditable() {
  	makeMetadataEditable(
  		$("#catalogMetadataWorkbenchContent > table > tbody > tr > td"),
  		updateProductMetadata);		
  }
  
  function makeProductTypeMetadataEditable() {
  	makeMetadataEditable(
  		$("#liveProductTypeWorkbenchContents div.ptwbMetadataList > table > tbody > tr > td"),
  		updateProductTypeMetadata);
  }
  
  function updateStagedMetadata() {
  	// Data is the collection of <tr/> elements that contain metadata key/value pairs
  	var data = getMetadataFromSource($('#stagedMetadataWorkbenchContent > table > tbody > tr'));
  	var qstr = getQueryStringFromMetadata(_paths.currentStagedFile, data);
  	
  	$.post('../services/metadata/staging',
  		qstr,
  		function(data, textStatus) {
  			// alert(data);
  		}
  	);
  }
  
  function updateProductMetadata() {
  	// Data is the collection of <tr/> elements that contain metadata key/value pairs
  	var data = getMetadataFromSource($('#catalogMetadataWorkbenchContent > table > tbody > tr'));
  	var qstr = getQueryStringFromMetadata(_paths.currentCatalogedFile, data);
  
  	$.post('../services/metadata/catalog',
  		qstr,
  		function(data, textStatus) {
  			// alert(data);
  		}
  	);
  }
  
  function updateProductTypeMetadata() {
  	// Data is the collection of <tr/> elements that contain metadata key/value pairs
  	var data = getMetadataFromSource($('#liveProductTypeWorkbenchContents div.ptwbMetadataList > table > tbody > tr'));
  	var qstr = getQueryStringFromMetadata(_paths.currentProductType, data);
  
  	$.post('../services/metadata/productType',
  		qstr,
  		function(data, textStatus) {
  			// alert(data);
  		}
  	);
  }
  
  
  
  /**
   * Utility functions to encapsulate common functionality
   *
   */
  
  // source:   the collection of <td/> objects containing metadata values
  // callback: the function to be called to persist the edits
  function makeMetadataEditable(source, callback) {
  	// Set up the i/f to display the icon only when the user is hovering over
  	// the field
  	source.click(function() {
  		var $met = $(this);
  		var metValue = $met; // the <td> itself
  			var metKey = $(this).prev().text();
  			jPromptMulti(
  					metKey,
  					metValue,
  					'Update Metadata',
  					function(r) {
  
  						if (r) {
  							// turn r into a comma-separated string of values
  							htmlResult = '<span>' + r.join('</span>, <span>') + '</span>';
  							// alert( 'You entered ' + htmlResult )
  							$met.html(htmlResult);
  							callback();
  						}
  					});
  		});
  }
  
  function getMetadataFromSource( source ) {
  	
  	// Keys are 1 per row in <th/> elements
  	// Values are 1 per row in <td/> elements
  	
  	var $table = source;
  	var data   = Array();
  	$table.each( function () {
  		// Create a key/value mapping of the staged metadata
  		var $valueElmt = $(this).children('td');
  		// All values are wrapped in <span/> elements and there can be
  		// an unlimited number of them, so build an array.
  		var $values    = $valueElmt.children('span');
  		var valueData  = Array();
  		for (var i = 0; i < $values.length; i ++ ) {
  			valueData.push($values[i].textContent);
  		}
  		// Assign the value data to the correct element
  		data.push( { 'key' : $(this).children('th').text(), 'value' : valueData } );
  	});
  	
  	return data;
  }
  
  function getQueryStringFromMetadata(id,data) {
  	// Build the query string that will be sent to the server
  	var qstr      = '';
  	qstr         += 'id=' + id;
  	for ( var i = 0; i < data.length; i++ ) {
  		for ( var j = 0; j < data[i].value.length; j++ ) {
  			qstr += '&metadata.' + data[i].key + '=' + data[i].value[j];
  		}
  	}
  	
  	return qstr;
  }
  
  
  /********************************************************************
   * INGESTION TASK SETUP
   */
  
  
  // Keep track of dropped files. This is used to determine the files 
  // that will be included in an ingestion task
  var droppedFiles = Array();
  
  // The currently selected policy. This is the policy that will
  // be used in the ingestion task.
  var itPolicy;
  
  // The currently selected product type. This is the product typte that
  // will be used in the ingestion task
  var itProductType;
  
  
  // The currently selected Metadata Extractor Configuration Id
  // This is the configuration that will be sent with the ingestion task
  var itMetExtractorConfigId = 'default';
  
  
  
  function updateIngestionTaskMetExtractorConfigIds() {
  	$.get('../services/metadata/extractor/config',
  			{},
  			function(data,textState) {
  				$('#itMetExtractorConfigId').html(data);
  				itMetExtractorConfigId = $('#itMetExtractorConfigId').val();
  			});
  }
  
  function updateSelectedMetExtractorConfigId() {
  	itMetExtractorConfigId = $('#itMetExtractorConfigId').val();
  }
  
  function createIngestionTask() {
  	// The files to include are in droppedFiles
  	var files       = droppedFiles;
  	// The met extractor config id is in itMetExtractorConfigId
  	var metExtCfgId = itMetExtractorConfigId;
  	// The policy and product type are in itPolicy and itProductType
  	var policy      = itPolicy;
  	var productType = itProductType;
  	// Other variables we'll need
  	var numFiles = droppedFiles.length;
  	
  	// Send the information to the create ingestion task servlet
  	$.get('../services/ingest/create',
  			{
  				'files'      : files.join(','),
  				'numfiles'   : numFiles,
  				'metExtCfgId': metExtCfgId,
  				'policy'     : policy,
  				'ptype'      : productType
  			},
  			function (data,textState) {
  			   refreshIngestTaskList();		
  			}); 
  	
     
  }
  
  function refreshIngestTaskList(){
      $.get('../services/ingest/list',
              { 'format': 'html'
              },
              function (data,textState) {
                  showIngestionTaskList(data);
              });         
  }
  
  function showIngestionTaskList(data){
      $('#ingestionTaskListItems > tbody').html(data);
  }
  
  function registerIngestionTaskListener(){
      $.PeriodicalUpdater('../services/ingest/list', {
          method: 'get',         
          data: { 'format:': 'html'},          
          minTimeout: 1000,
          maxTimeout: 60000,
          multiplier: 2
        }, function (data) {
            showIngestionTaskList(data);
           });
  
  }
  
  function createIngestionTaskRow(data) {    
      $('#ingestionTaskListItems > tbody').replace(data);
  }
  
  function removeIngestionTask(id) {
  	$.get('../services/ingest/remove',
  			{ 'taskId' : id },
  			refreshIngestTaskList()
  			);
  }
  
  function startIngestionTask(id) {
  	$.get('../services/ingest/start',
  			{ 'taskId' : id },
  			function(data,textState) {
  				$('#'+id+'_Status').html(data);	// 'started' or 'error'
  				refreshIngestTaskList();
  			});
  }
  
  /********************************************************************
   * DRAG AND DROP INITIALIZATION AND CONFIGURATION
   * 
   */
  function initDraggables() {
  	$('.draggy').draggable({
  		revert:true, 
  		zIndex:'5000', 
  		appendTo:'body'
  		, 
  		helper: function() { 
  			return $('<li>')
  				.addClass('helper')
  				.addClass('file').addClass('ext_tiff')
  				.html($(this).children().clone());
  		}
  	});
  }
  function initDragAndDropTarget() {
  	$('#droppedFileTarget').droppable( {
  		drop: function(event, ui) {
  			droppedFiles.push(ui.draggable.children('a')[0].rel);
  			updateDroppedFilesList();
  		}
  	});
  }
  function updateDroppedFilesList() {
  	var i = droppedFiles.length -1;
  	$('#droppedFileList > ul').append(
  		'<li rel="'+droppedFiles[i]+'">'+droppedFiles[i]+'</li>'
  	);
  }
  function clearDroppedFilesList() {
  	droppedFiles = Array();				// clear the js array
  	$('#droppedFileList ul').html('');	// clear the interface display
  }
  
  
  /********************************************************************
   * MAIN INITIALIZATION FUNCTION (ON DOM READY)
   */
  $(document).ready( function() {
  
  	// Initialize the staging area browser
  	initStagingAreaBrowser();
  	
  	// Initialize the staging area navigation buttons
  	$('#stagingNavUpOne')
      	.dblclick(stagingNavigateUpOne)
      	.click( function(event) {event.preventDefault();});
      $('#stagingNavUpRoot')
      	.dblclick(stagingNavigateUpRoot)
      	.click( function(event) {event.preventDefault();});
  
  
  	// Initialize the File Manager browser
  	initFileManagerBrowser();
  
  	// Initialize the catalog navigation buttons
  	$('#catalogNavUpOne')
  		.dblclick(catalogNavigateUpOne)
      	.click( function(event) {event.preventDefault();});
  	$('#catalogNavUpRoot')
  		.dblclick(catalogNavigateUpRoot)
      	.click( function(event) {event.preventDefault();});
  
  
  	// Make overlaid info messages semi-transparent
  	$('.info.overlay').fadeTo(0,0.8);
  	
  	// Connect staging met extractor refresh button
  	$('#stagingMetExtractorRefreshButton').click(refreshStagedMetadata);
  	
  });
  
  function updateNav(which) {
  	if (which == 'staging') 
  		$('#browseStagingPath').html('Path: ' + _paths.staging);
  		if ('/' == _paths.staging) {
  			// We are at the root, don't show . and ..
  			$('#browseStagingNav').hide();
  		} else {
  			$('#browseStagingNav').show();
  		}
  	if (which == 'catalog') {
  		// Catalog navigation is a little more complex
  		$('#browseCatalogPath').html('Path: ' + _paths.catalog);
  		if ('/' == _paths.catalog) {
  			// We are listing policies, don't show . and ..
  			$('#browseCatalogNav').hide();
  		} else {
  			$('#browseCatalogNav').show();
  		}
  
  	}
  }
  
  function clearMetadataWorkbenchContent(which) {
  	if (which == 'staging') {
  		$('#infoNoMetadataExtractorDefined').hide();
  		$('#stagedMetadataWorkbenchContent').html('');
  		hideStagingMetExtractorSelection();
  		_paths.currentStagedFile = '';
  	} else if (which == 'catalog') {
  		$('#catalogMetadataWorkbenchContent').html('');
  		_paths.currentCatalogedFile = '';
  		_paths.currentProductType   = '';
  	}
  }
  
  
  
  /********************************************************************
   * STAGING AREA BROWSER FUNCTIONS
   */
  
  var stagingMetExtractorConfigId = '';
  
   
  function initStagingAreaBrowser() {
  	 $('#browseStagingContents').fileTree(
      	{ root:   '/',
            which:  'staging',
            script: '../services/directory/staging' 
          }, function(file) {
          	getMetadataForStagedFile(file, false);
        });
       updateNav('staging');
  }
  
  function stagingNavigateUpOne() {
  	var pieces = _paths.staging.split('/');
  	var newpath = '';
  	for (var i=0; i < (pieces.length-2); i++) {
  		newpath += (pieces[i] + '/');
  	}
  	if ('' == newpath) {
  		newpath = '/';
  	}
  	_paths.staging = newpath;
  	initStagingAreaBrowser();
  	clearMetadataWorkbenchContent('staging');
  	return false;
  }
  
  function stagingNavigateUpRoot() {
  	// Re-Initialize the staging area browser
  	_paths.staging = '/';
  	initStagingAreaBrowser();
  	clearMetadataWorkbenchContent('staging');
      return false;
  }
  
  function getMetadataForStagedFile(file, overwrite) {
  	$.get('../services/metadata/staging',
  			{ 'id' : file,
  		      'configId' : stagingMetExtractorConfigId,
  		      'overwrite' : overwrite
  			},
  			function(data,textStatus) {
  				displayStagedFileMetadata(file,data);
  			}, "html");
  }
  
  function displayStagedFileMetadata(file,data) {
  	showStagingMetExtractorSelection();
  	_paths.currentStagedFile = file;
  	if (! data.match('tr')) {
  		if (stagingMetExtractorConfigId == '') {
  			$('#infoNoMetadataExtractorDefined').show();
  		}
  	} else { 
  		$('#stagedMetadataWorkbenchContent').html(data);
  		makeStagedMetadataEditable();
  	}
  }
  
  function updateStagingMetExtractorConfigIds() {
  	$.get('../services/metadata/extractor/config',
  		{'current' : stagingMetExtractorConfigId },
  		function(data,textState) {
  			$('#stagingMetExtractorConfigList').html(data);
  			stagingMetExtractorConfigId = $('#stagingMetExtractorConfigList').val();
  		});
  }
  
  function showStagingMetExtractorSelection() {
  	$('#stagedMetadataWorkbenchContent').css('height','323px');
  	$('#stagingMetExtractorSelection').fadeIn('fast');
  	updateStagingMetExtractorConfigIds();
  }
  
  function hideStagingMetExtractorSelection() {
  	$('#stagingMetExtractorSelection').fadeOut('fast');
  	$('#stagedMetadataWorkbenchContent').css('height','350px');
  }
  
  function refreshStagedMetadata() {
  	stagingMetExtractorConfigId = $('#stagingMetExtractorConfigList').val();
  	getMetadataForStagedFile(_paths.currentStagedFile, true);
  }
  /********************************************************************
   * FILE MANAGER BROWSER FUNCTIONS
   */
  
  //
  // paths in this area are "virtual", that is, they reflect the logical
  // organization of the file manager catalog rather than the physical
  // organization of the products in the repository. As such, the virtual
  // path to a product is obtained by specifying both the 'policy' and 
  // 'productType':
  //
  // dem00001.tiff exists at "virtual" path: /Lmmp/DEM where
  // LMMP is the policy
  // and DEM is a product type defined within that policy
  //
  
   
  function initFileManagerBrowser() {
  	 $('#browseCatalogContents').fileTree(
      	{ root:   '/',
            which:  'catalog',
            script: '../services/policy/browse'
          }, function(file) {
          	getMetadataForCatalogedFile(file);
          }, function(productType) {
            getProductTypeWorkbench(productType);
       });
       updateNav('catalog');
       
  }
  
  function catalogNavigateUpOne() {
  	
  	var pieces = _paths.catalog.split('/');
  	var newpath = '';
  	for (var i=0; i < (pieces.length-2); i++) {
  		newpath += (pieces[i] + '/');
  	}
  	if ('' == newpath) {
  		newpath = '/';
  	}
  	_paths.catalog = newpath;
  	initFileManagerBrowser();
  	clearMetadataWorkbenchContent('catalog');
  	return false;
  }
  
  function catalogNavigateUpRoot() {
  	// Re-Initialize the catalog browser
  	_paths.catalog = '/';
  	initFileManagerBrowser();
  	clearMetadataWorkbenchContent('catalog');
  	return false;
  }
   
  function getMetadataForCatalogedFile(file) {
  	$.get('../services/metadata/catalog',
  			{ 'id' : file },
  			function(data,textStatus) {
  				displayCatalogedFileMetadata(file,data);
  				}, "html");
  }
   
  function displayCatalogedFileMetadata(file,data) {
  	$('#catalogMetadataWorkbenchContent').html(data);
  	_paths.currentCatalogedFile = file;
  	makeProductMetadataEditable();
  }
  
  function getProductTypeWorkbench(productType) {
  	var pieces = productType.split('/');
  	var policy = pieces[1];
  	var ptype  = pieces[2];
  	$.get('../services/metadata/productType',
  			{ 'policy' : policy, 'productType' : ptype, 'id' : productType },
  			function(data,textStatus) {
  				displayProductTypeWorkbench(productType,data);
  			},"html");
  	itPolicy      = policy;
  	itProductType = ptype;
  }
  
  function displayProductTypeWorkbench(productType,data) {
  	$('#catalogMetadataWorkbenchContent').html('');	// clear the old contents
  	$('.ptwbMetadataList').html(data);				// add metadata from service		
  	
  	$('#productTypeWorkbenchContents')				// display pt workbench
  		.clone()
  		.attr('id','liveProductTypeWorkbenchContents')
  		.appendTo('#catalogMetadataWorkbenchContent')
  		.show()
  		.tabs();
  	clearDroppedFilesList();						// clear dropped files list
  	initDragAndDropTarget();						// set up the d&d target box
  	_paths.currentProductType = productType;		// set the path for the ptype
  	makeProductTypeMetadataEditable();				// allow ptype met editing
  	updateIngestionTaskMetExtractorConfigIds();
  }
  
  
  