
Unknown=0	// hack to fix bad data from database.

// Products (and Datasets)  ==============================================

// the raw data is created by a cron job, and is found in productData.js
// the data is stored in:
//	datasets
//	productData
//	productExtents

// ---- provide the ability to convert from id to array element

// a function to convert Id to array index for each of productData, productExtents and datasets
function IdToIndex( id, object ) { return object.lookup[ id ]; }

// build the lookup tables
function buildLookups() {
	// productData
	productData.lookup=[];
	for (i=0; i<productData.length; i++) {
		var id=productData[ i ].id;
		productData.lookup[ id ] = i;
	}
	// productExtents
	productExtents.lookup=[];
	for (i=0; i<productExtents.length; i++) {
		var id=productExtents[ i ].id;
		productExtents.lookup[ id ] = i;
	}
	// datasets
	datasets.lookup=[];
	for (i=0; i<datasets.length; i++) {
		var id=datasets[ i ].id;
		datasets.lookup[ id ] = i;
	}
}


// ---- set up an array to hold all the product information in an easy-to-access
var prod = {};

prod.ids =  [] ;
prod.names =  [] ;
prod.descriptions =  [] ;
prod.region = [] ;	// geographic extent for this product
prod.dateRange = [] ;	// temporal extent for this product

function initialiseProductArrays() {
	// make sure we can look up tables by id
	buildLookups();

	// default region for products that haven't got one defined.
	var regiondefault = [ -65, 90, 10, 185 ];
	prod.defaultRegion = regiondefault;

	prod.productCount=productData.length;
	prod.selectedIndex="none";

	// when we build the prod array, it will have the same number of elements as the productData array.  
	// really, we should just use the productData array.  That will require a code-cleanup.
	for (i=0; i<productData.length; i++) {

		var data=productData[i];

		prod.ids[i] = data.id;
		prod.names[i] = data.name;
		prod.descriptions[i] = data.description;

		// extents
		var j =  IdToIndex( data.id, productExtents );
		if ( productExtents[j] ) {
			var extents=productExtents[j].extents;
		} else { 
			var extents=null;
		}
		if ( extents ) {
			prod.region[i] = [ extents.lat[0], extents.lon[0], 
					extents.lat[1], extents.lon[1] ];
			prod.dateRange[i] = [ extents.dateTime[0], extents.dateTime[1] ];
		} else {
			prod.region[i] = [ regiondefault[0], regiondefault[1],
						regiondefault[2], regiondefault[3] ] ;
			prod.dateRange[i] = [ "", "" ];
		}
	}
}

// -------- build the menus -----------------------

// build the datasets menu.  
function buildDatasetsMenu() {
	var selected;
	selected='';
	appendOptionLast(datasetMenu, "all", "All Datasets", selected, "datasetSelect()");	
	selected='';
	for (i=0; i<datasets.length; i++) {
		selected=''; 
		appendOptionLast(datasetMenu, datasets[i].id, datasets[i].name, selected, "datasetSelect()" );
	}
}

// build the products menu.  

// The first argument is a function that will return an array of product ids.
// The second argument is a single value (may be an object or an array) for the function.
//  both arguments are optional
function buildProductsMenu( selectFunction, functionArgument ) {
	if ( selectFunction == null ) { selectFunction=selectAllProducts; }
	var selected='';
	var productList=selectFunction(functionArgument);
	// appendDisabledOptionLast(productMenu, "none" , "--Select a Product--" );	
		// .. the option didn't display by default! what is the point, I ask you?
	appendOptionLast(productMenu, "none" , "--Select a Product--", selected, "productSelectMessage()" );	
	for (i=0; i<productList.length; i++) {
		j=IdToIndex( productList[i], productData );
			// product data indexes correlate by definition to prod indexes.
		appendOptionLast(productMenu, prod.ids[j], prod.names[j], selected, "productSelect()" );	
	}
	// if there is only one product, select it.
	if ( 1==productList.length ) {
		productMenu[ 1 ].selected="selected";
		productSelect(1);	// 0 is the 'select product' message. 1 is the first `real' product
	}
}
function productSelectMessage() {
	selectedProductDescription.innerHTML = "";
}

// select functions that can be used to build a products menu..
function selectAllProducts() {
	var result = [];
	for (i=0; i<prod.productCount; i++) {
		result[i]=prod.ids[i];
	}
	return result;
}
function selectProductsForDatasetId( datasetId ) {
	selectProductsForDatasetIndex( datasetIdToIndex( datasetId ));
}
function selectProductsForDatasetIndex( datasetIndex ) {
	var productList=datasets[ datasetIndex ].products;
	return productList;
}

// append a new option to the end of a selection 
// pass in the selection element, and the value and text for the new option.
// optionally, pass in the selection value ("selected", can only be one of these.)
// adapted from http://www.mredkj.com/tutorials/tutorial005.html

// selectCallback is a string containing the javascript to be called when a mouseup event is detected.

function appendOptionLast(selectionElement, optionValue, optionText, selected, selectCallback) {
	// the pull-down menu element
	var elSel = selectionElement; 

	// create a new menu option, and set the attributes
	var elOptNew = document.createElement('option');
	elOptNew.value = optionValue;
	elOptNew.text = optionText;
	if ( selected ) { 
		elOptNew.setAttribute('selected','selected');
	}
	elOptNew.setAttribute('onmouseup',selectCallback);

	// add the new menu option to the pull-down menu.
	try {
		elSel.add(elOptNew, null); // standards compliant; doesn't work in IE
	}
	catch(ex) {
		elSel.add(elOptNew); // sub-standard.  eg. IE 
	}
}
function appendDisabledOptionLast(selectionElement, optionValue, optionText) {
	// the pull-down menu element
	var elSel = selectionElement; 

	// create a new menu option, and set the attributes
	var elOptNew = document.createElement('option');
	elOptNew.value = optionValue;
	elOptNew.text = optionText;
	elOptNew.setAttribute('disabled','disabled');

	// add the new menu option to the pull-down menu.
	try {
		elSel.add(elOptNew, null); // standards compliant; doesn't work in IE
	}
	catch(ex) {
		elSel.add(elOptNew); // sub-standard.  eg. IE 
	}
}


// remove the last option from a menu
function removeOptionLast(selectionElement) {
	// the pull-down menu element
	var elSel = selectionElement; 

	if (elSel.length > 0)
	{
		elSel.remove(elSel.length - 1);
	}
}

// remove all options from a menu
function clearMenu(selectionElement) {
	while (selectionElement.length > 0) {
		removeOptionLast(selectionElement);
	}
}

// what to do when a dataset is selected
// (build product menu for that dataset)
function datasetSelect() {
	var i=datasetMenu.selectedIndex ;       // option# user has selected
	clearMenu( productMenu );
	clearProductExtents();
	prod.selectedIndex="none";      // used when the cgi is called
	productSelectMessage();
	if ( i == 0 ) {
		// all products
		buildProductsMenu();
	} else {
		buildProductsMenu( selectProductsForDatasetIndex , i-1 );
	}
}

// what to do when a product is selected
// display name and description of the currently selected product.
function productSelect(i) {
	if ( i == null ) {
		i=productMenu.selectedIndex ;	// option# user has selected 
	}
	var val=productMenu.value;	// a product id
	if ( val == "none" ) {
		clearProductExtents();
		prod.selectedIndex="none";	// used when the cgi is called
		return;
	}
	i=IdToIndex( val, productData ); // the index within the prods array.
	prod.selectedIndex=i;		// used when the cgi is called
	displaySelectedProduct(i);
	displayProductExtents(i);
}

function displaySelectedProduct(i) {
	selectedProductDescription.innerHTML = prod.descriptions[i];	

	var extraInfo="";
	if ( prod.region[i].length ) {
		extraInfo="<br>(extends from: "+
			prod.region[i][0]+" N, "+prod.region[i][1]+" E to "+	
			prod.region[i][2]+" N, "+prod.region[i][3]+" E )";
	}
	if ( prod.dateRange[i].length ) {
		extraInfo+="<br>(data available from: "+
			prod.dateRange[i][0]+" to: "+prod.dateRange[i][1]+" )";	
	}
	extraInfo+="<a href='#' class='productExtraInfo' onclick='openProductExtraInfo("+prod.ids[i]+");'> more ... </a>"
	document.getElementById("selectedProductDescription").innerHTML += extraInfo;
}

function openProductExtraInfo(i) {
	cgiApplication="productExtraInfo.cgi.sh";
	url=cgiURL+'?'+runtimeEnvironment+','+cgiApplication+","+i;
	window.open( url );	
}

//
// Display the outer extent polygon(s)
//
var extentpolys;
var extentmarkers;
function clearProductExtents() {
	var p;
	if(extentpolys) {
                for (p in extentpolys) {
		      map.removeOverlay(extentpolys[p]);
		}
	}
	if(extentmarkers) {
                for (p in extentmarkers) {
		      map.removeOverlay(extentmarkers[p]);
		}
	}
}
function displayProductExtents(i) {
	if ( i == -1 ) {
		// happends when we first load the page.  No product has been selected yet,
		// but we try to display the product extents when we build the map.
		return;
	}
	if ( i == "none" ) { return; }
	clearProductExtents();
	var pregion;
	if ( prod.region[i].length ) {
		pregion=prod.region[i];
	} else {
		pregion=prod.defaultRegion;
	}
        //var outer=new GLatLngBounds(
        //        new GLatLng( pregion[0], pregion[1] ),
        //        new GLatLng( pregion[2], pregion[3] ) );
        var outer = [] ;
        outer.push( new GLatLng(pregion[2], pregion[3]) );
        outer.push( new GLatLng(pregion[2], pregion[1]) );
        outer.push( new GLatLng(pregion[0], pregion[1]) );
        outer.push( new GLatLng(pregion[0], pregion[3]) );
        outer.push( new GLatLng(pregion[2], pregion[3]) );
        extentpolys=drawOuterRegion(outer);
        for (p in extentpolys) {
                map.addOverlay( extentpolys[p] );
        }
        extentmarkers = [] ;
	var x;
        for (x in outer) {
            var m = gmarker.newExtentsMarker(outer[x]);
            map.addOverlay( m );
            extentmarkers.push(m);
        }
}


