/*
  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();
}


