/******************************************************************************
 *                                                                            *
 *  Copyright (C) 2008-2010 Alexander Barth <barth.alexander@gmail.com>.      *
 *                                                                            *
 *  This program is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU Affero General Public License as published  *
 *  by the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                       *
 *                                                                            *
 *  This program is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *  GNU Affero General Public License for more details.                       *
 *                                                                            *
 *  You should have received a copy of the GNU Affero General Public License  *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.     *
 *                                                                            *
 ******************************************************************************/

"use strict";

var OceanBrowser = {};

OceanBrowser.UI = {};

OceanBrowser.UI.makedom = function(tag,attr,children) {
    var elem, i;
    attr = attr || {};
    children = children || {};

    elem = $('<' + tag + '></' + tag + '>');
    elem.attr(attr);

    for (i=0; i < children.length; i++) {	
	elem.append(children[i]);
    }
    return elem.get()[0];
};

OceanBrowser.UI.BaseDialog = EarthGL.Class({
	events: null,
	div: null,
	id: null,

	initialize: function(divid,title) {	    
	    this.events = new EarthGL.Events(this);
	    this.id = divid;
	    this.div = document.createElement('div');
	    this.div.id = divid;
	    this.div.title = title;
	    document.body.appendChild(this.div);
	},

	open: function() {
	    $(this.div).dialog('open');
	},

	close: function() {
	    $(this.div).dialog('close');
	}
    });

OceanBrowser.UI.chooseServer = EarthGL.Class(OceanBrowser.UI.BaseDialog,{

	initialize: function(id,servers) {
	    OceanBrowser.UI.BaseDialog.prototype.initialize.apply(this,[id + '_add_server_dialog','Add server']);

	    // better clone
	    this.servers = [{name: 'new',
			     title: 'New Server',
			     url: '',
			     version: '1.3.0',
			     extension: 'none' }].concat(servers);

	    $(this.div).append('\
      <p class="instruction">Choose either a server from the server list or enter the URL of a WMS server directly.</p>\
      <table>\
	<tbody>\
	  <tr>\
	    <td>\
	      Server:\
	    </td>\
	    <td>\
	      <select id="' + id + '_wms_server">\
	      </select>\
	    </td>\
	  </tr>\
	  <tr>\
	    <td>\
	      WMS URL:\
	    </td>\
	    <td>\
	      <input type="text" size="40" id="' + id + '_wms_url" /> \
	    </td>\
	  </tr>\
	  <tr>\
	    <td>\
	      WMS version:\
	    </td>\
	    <td>\
	      <select id="' + id + '_wms_version">\
		<option>1.3.0</option>\
		<option>1.1.1</option>\
	      </select>\
	    </td>\
	  </tr>\
	</tbody>\
      </table>\
\
      <br />\
      <input type="button" value="Close"id="' + id + '_add_server_dialog_close" /> \
      <input type="button" value="Add" id="' + id + '_add_server_dialog_ok" /> <br />\
');
    

    // HTML elements for callback
    this.elem = {};
    this.elem.url = document.getElementById(id + '_wms_url');
    this.elem.version = document.getElementById(id + '_wms_version');
    this.elem.list = document.getElementById(id + '_wms_server');
    this.elem.close = document.getElementById(id + '_add_server_dialog_close');
    this.elem.add = document.getElementById(id + '_add_server_dialog_ok');

    // contruct list of servers
    var oOption;

    for (var i = 0; i < this.servers.length; i++) {
        oOption = this.elem.list.appendChild(document.createElement("option"));
        oOption.value = "" + i;
        oOption.appendChild(document.createTextNode(this.servers[i].title));
    }


    $(this.div).dialog({ autoOpen: false, width: 500});

    var that = this;

    $(this.elem.list).change(function() {
	    var i = parseInt($(this).val(),10);
	    
	    $(that.elem.url).val(that.servers[i].url);
	    $(that.elem.version).val(that.servers[i].version);
	});

    $(this.elem.close).click(function() {
	    that.close();
	});

    $(this.elem.add).click(function() {
	    var i = parseInt($(that.elem.list).val(),10);

	    var server = {
		url: $(that.elem.url).val(),
		version: $(that.elem.version).val(),
		extension: that.servers[i].extension 
	    };

	    that.events.triggerEvent('serverSelected',server);
	    that.close();
	});

	}


    });




OceanBrowser.UI.InfoLayer = EarthGL.Class(OceanBrowser.UI.BaseDialog,{

	initialize: function(id,layer) {
	    OceanBrowser.UI.BaseDialog.prototype.initialize.apply(this,[id + '_info_layer_dialog','Info Layer']);

	    var that = this,
	    attr, bbox, $prod, dim, preview;

	    function make_table(name,elem) {
		var i, $tbody2;

		if (name) {
		    $(that.div).append($('<h4/>').html(name));
		}

	        $tbody2 = $('<tbody/>');		    
		
		for (i=0; i<elem.length; i++) {
		    $tbody2.append($('<tr/>')
				  .append($('<td/>').attr({width: '100'}).append(elem[i][0]))
				  .append($('<td/>').append(elem[i][1]))
				  );
		}

		$(that.div).append($('<table/>').attr({width: '100%'}).addClass('tableInfo').append($tbody2));
	    }


	    function make_link(url) {
		return $('<a/>').attr({'href': url,'target': '_blank'}).append(url);
	    }

    
	    attr = layer.get_attribution();
	    $prod = $('<span/>');

	    if ('title' in attr) {
		if ('url' in attr) {
		    $prod = $('<a/>').attr('href',attr.url).html(attr.title);

		}
		else {
		    $prod = $('<span/>').html(attr.title);
		}

		if ('logo' in attr) {
		    $prod.append($('<img/>').attr({'src': attr.logo,'class': 'attribution_logo'}));
		}	       	    
	    }

	    bbox = layer.get_bounding_box();

	    /*
	    var params = {
		    'layers': decodeURIComponent(layer.name),
		    'service': 'WMS', 
		    'request': 'GetMap', 
		    'version': layer.cap.version,
		    'exceptions': 'application/vnd.ogc.se_inimage',
		    'format': 'image/png',
		    'bbox': bbox.join(','),
		    'width': 128,
		    'height': 128
		}

	    var styles = layer.get_styles()
	    var $legend = $('<span/>');
	    if (styles.length > 0) {
		$legend = $('<img/>').attr({'src': styles[0].legend_url,'alt': 'legend'});
	    }

	    preview = Util.append_param(layer.wms_url,params);
	    params.layers = baselayer_name;
	    var preview_background = Util.append_param(baselayer_url,params);
	    

	    var $preview =  $('<div/>')
    	       .append($('<span/>').css({'position': 'relative', 
					    'height': params['height'],
					    'width': params['width']})
		   .append($('<img/>')
			   .css({'position': 'absolute'})
			   .attr({'src': preview_background,'alt': 'preview'})
			   )
		   .append($('<img/>')
			   .css({'position': 'absolute'})
			   .attr({'src': preview,'alt': 'preview'})
			   ));

	    if (styles.length > 0) {
		$preview.append($('<img/>').attr({'src': styles[0].legend_url,'alt': 'legend'}));
	    }
	    */

	    make_table('Data',[['Title',layer.title],
			       ['Producer',$prod],
			       ['Abstract',layer.abstract_info] /*,
			       ['Preview',$preview],
			       ['Legend',$legend] */
			       ]);

	    // Bounding box

	    make_table('Bounding box',[['Northern limit',bbox[3]],
				       ['Southern limit',bbox[1]],
				       ['Western limit',bbox[0]],
				       ['Eastern limit',bbox[2]]]);	    
	    
	    // Dimensions
	    
	    dim = layer.get_dimension('time');

	    make_table('Time',[['Time units',dim.units],
			       ['Time range',dim.range.join(', ')]]);
	     
	    dim = layer.get_dimension('elevation');
	    make_table('Depth',[['Depth units',dim.units],
			       ['Depth range',dim.range.join(', ')]]);

	    // Download
	    make_table('Data Access',[['HTTP',make_link(layer.http_url)],
				      ['OPeNDAP',make_link(layer.opendap_url)],
				      ['Metadata',make_link(layer.metadata_url)]]);


	    make_table('Web Map Service',[['Server',layer.wms_url],
					  ['Name',layer.name],
					  ['Version',layer.cap.version]]);
	   

	    $(this.div).dialog({ autoOpen: false, width: 700, height: 600});
	}
    });



OceanBrowser.UI.chooseLayer = EarthGL.Class(OceanBrowser.UI.BaseDialog,{

	initialize: function(id,servers,baselayer) {
	    OceanBrowser.UI.BaseDialog.prototype.initialize.apply(this,['add_layer_dialog','Add layer']);
	    this.id = id;

	    var that = this;

	    $(this.div).append('\
  WMS Server: \
  <span id="' + id + '_wms_server_name">	\
  </span>\
\
  <button id="' + id + '_add_server_button" style="float: right" >Add Server</button>\
\
  <fieldset style="width: 622px">\
  <legend>Layer</legend>	\
  <div style="height: 150px;  overflow:auto;" id="' + id + '_chooser"></div>\
  </fieldset>\
  <fieldset style="width: 330px; height: 140px; float: left">\
    <legend>Section type</legend>\
    <p>\
      <label><input type="radio" id="' + id + '_horizontal_section" name="section_type" value="horizontal" checked />Horizontal</label>\
    </p>\
    <p>\
      <label><input type="radio" id="' + id + '_vertical_section" name="section_type" value="vertical" />Vertical  (draw a vertical section with the mouse in the preview panel)</label>\
    </p>\
  </fieldset>\
  <fieldset style="width: 260px; height: 140px; float: left">\
    <legend>Preview</legend>\
    <div id="' + id + '_vert_map_selection" style="width: 250px; height: 125px"></div>\
  </fieldset>\
  <br style="clear: both"/>\
  <div style="float: right; padding-top: 10px">\
    <button type="button" id="' + id + '_add_layer_dialog_close">Close</button>\
    <button type="button" id="' + id + '_add_layer_dialog_ok">Add layer</button>\
  </div>\
');

	    $('#add_layer_dialog').dialog({ autoOpen: false, width: 700, height: 480, zIndex: 3999 }); 

	    this.loadServer(servers[0]);
	    
	    this.chooseServer = new OceanBrowser.UI.chooseServer('chooseServer',servers);
	    this.chooseServer.events.register('serverSelected', this, this.loadServer);

	    // HTML elements for callback
	    this.elem = {};
	    this.elem.server = document.getElementById(id + '_add_server_button');
	    this.elem.hs = document.getElementById(id + '_horizontal_section');
	    this.elem.vs = document.getElementById(id + '_vertical_section');
	    this.elem.close = document.getElementById(id + '_add_layer_dialog_close');
	    this.elem.ok = document.getElementById(id + '_add_layer_dialog_ok');
	    this.elem.name = document.getElementById(id + '_wms_server_name');

	    $(this.elem.server).click(function() {
		    that.chooseServer.open();
		});


	    this.map_selection = new OpenLayers.Map(id + "_vert_map_selection",
					    {maxResolution: 180/128,
					     maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90) ,
					     theme: null 
					    });
    
	    var options = {
		resolutions: [1.40625,
			      0.703125,
			      0.3515625,
			      0.17578125,
			      0.087890625,
			      0.0439453125,
			      0.02197265625,
			      0.010986328125,
			      0.0054931640625,
			      0.00274658203125,
			      0.00137329101]
	    };

	    
	    if (baselayer) {
		this.mini_baselayer_wms = new OpenLayers.Layer.WMS("Continents",baselayer.url, 
								   {layers: baselayer.name, 
								    format: baselayer.format},
								   options);
		this.map_selection.addLayer(this.mini_baselayer_wms);
	    }

	    var style = OpenLayers.Util.applyDefaults({strokeWidth: 2, strokeColor: "black"}, 
						      OpenLayers.Feature.Vector.style["default"]);

    

	    this.vectors = new OpenLayers.Layer.Vector("Vector Layer", {style: style});
	    this.control = new OpenLayers.Control.DrawFeature(this.vectors,OpenLayers.Handler.Path, {handlerOptions: {style: style}});

	    this.map_selection.addLayer(this.vectors);
	    this.vectors.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);

	    this.map_selection.addControl(this.control);
    


	    $(this.elem.hs).click(function() { 
		    that.control.deactivate();
		});

	    $(this.elem.vs).click(function() { 
		    that.control.activate();
		    // for some reasons "control.deactivate" demotes the ZIndex for the vector layer
		    that.vectors.setZIndex(that.map_selection.Z_INDEX_BASE.Feature);
		    that.control.handler.layer.setZIndex(that.map_selection.Z_INDEX_BASE.Feature+1);
		});


	    $(this.elem.close).click(function() { 
		    that.close();
		});

	    $(this.elem.ok).click(function() { 
		    that.close();
		    that.getSectionObj();
		});
	},
	

	loadServer: function(server) {
	    var that = this;
	    // added var here
	    var cap = new OceanBrowser.UI.LayerTree(this.id + "_chooser",server.url,{namespace: 'layer_list1_',choose_multiple: false});
	    cap.events.register('layerSelected', this, this.fieldSelected);
	    cap.events.register('loaded', this, function() {
		    this.elem.name.innerHTML = cap.title;
		});
	    
	    //cap.events.register('loaded',null, test_ui);

	    cap.load();   	    	   
	},

	fieldSelected: function(field) {
	    var display_param = {style: '', param: {}};

	    if (this.layerWMS) {
		this.map_selection.removeLayer(this.layerWMS);
	    }

	    this.layerWMS = new OpenLayers.Layer.WMS(field.title,
						     field.wms_url,
{layers: decodeURIComponent(field.name), 
 styles: display_param.style,
 transparent: "true", format: "image/png"});

	    this.layerWMS.mergeNewParams(display_param.param);
	    this.map_selection.addLayer(this.layerWMS);
	    this.layerWMS.setZIndex(this.map_selection.Z_INDEX_BASE.Overlay);
	    this.vectors.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);
	    this.selection = field;

	},

	getSectionObj: function() {
	    var constraints = {};
	    if (this.elem.hs.checked) {
		constraints.type = 'lon-lat';		
	    }
	    else {
		constraints.type = 'section-depth';		
		this.vectors.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);
		var c = this.vectors.features[this.vectors.features.length-1].geometry.components;
		constraints.lon = [];
		constraints.lat = [];

		for (var i=0; i < c.length; i++) {
		    constraints.lon.push(c[i].x);
		    constraints.lat.push(c[i].y);
		}	       		
	    }
	    
	    this.events.triggerEvent('layerSelected',{field: this.selection,
			constraints: constraints});

	},

	open: function() {
	    $(this.div).dialog('open');
	    this.map_selection.zoomToMaxExtent();	    
	}

    });


OceanBrowser.UI.LayerDownload = EarthGL.Class(OceanBrowser.UI.BaseDialog,{
	mimetypes: {
	    'image/png': 'PNG',
	    'application/vnd.google-earth.kmz': 'KML',
	    'application/pdf': 'PDF',
	    'image/eps': 'EPS',
	    'image/svg+xml': 'SVG'},


/**
 * OceanBrowser.UI.LayerDownload 
 * dialog for download a layer (as data or as image)
 * @param {String} id Identifier (must be unique)
 * @param getCurrentExtent is a function which returns a structure (left, right, bottom, top)
 * @constructor
 */


	initialize: function(id,layer,getCurrentExtent,formats) {
	    var that = this, dom = OceanBrowser.UI.makedom, i;
	    this.layer = layer;
	    this.getCurrentExtent = getCurrentExtent;

	    formats = formats || ['image/png', 'application/vnd.google-earth.kmz', 'application/pdf', 'image/eps', 'image/svg+xml'];

	    OceanBrowser.UI.BaseDialog.prototype.initialize.apply(this,[id + 'download_dialog','Download layer']);

	    // DOM tree for Download Dialog
	    $(this.div).append(
              dom('div',{'class': 'OceanBrowserDownloadDialog'},[
                   dom('h3',{},[
                       'Data:'
                   ]),
                   dom('table',{},[
                       dom('tbody',{},[
                           dom('tr',{},[
                               dom('td',{},[
				   dom('a',{'href': layer.http_url, 'target': '_blank'},[
                                       'HTTP:'
                                   ])
                               ]),
                               dom('td',{},[
				   dom('input',{'readonly': 'readonly', 'type': 'text', 'size': '40', 'value': layer.http_url})
                               ])
                           ]),
                           dom('tr',{},[
                               dom('td',{},[
				      dom('a',{'href': layer.opendap_url, 'target': '_blank'},[
                                       'OPeNDAP:'
                                   ])
                               ]),
                               dom('td',{},[
        			   dom('input',{'readonly': 'readonly', 'type': 'text', 'size': '40', 'value': layer.opendap_url})
                               ])
                           ])
                       ])
                   ]),
                   dom('h3',{},[
                       'Image:'
                   ]),
                   dom('table',{},[
                       dom('tbody',{},[
                           dom('tr',{},[
                               dom('td',{},[
                                   dom('label',{'for': this.id + 'imageWidth'},[
                                       'Width (px):'
                                   ])
                               ]),
                               dom('td',{},[
                                   this.imageWidth = dom('input',{'type': 'text', 'id': this.id + 'imageWidth', 'value': '800', 'size': '5'})
                               ]),
                               dom('td',{},[
                                   dom('label',{'for': this.id + 'imageHidth'},[
                                       'Height (px):'
                                   ])
                               ]),
                               dom('td',{},[
                                   this.imageHeight = dom('input',{'type': 'text', 'id': this.id + 'imageHeight', 'value': '500', 'size': '5'})
                               ])
                           ]),
                           dom('tr',{},[
                               dom('td',{},[
                                   dom('label',{'for': this.id + 'rxmin'},[
                                       'x-range:'
                                   ])
                               ]),
                               dom('td',{},[
                                   this.rxmin = dom('input',{'type': 'text', 'id': this.id + 'rxmin', 'size': '5'}),
                                   this.rxmax = dom('input',{'type': 'text', 'id': this.id + 'rxmax', 'size': '5'})
                               ]),
                               dom('td',{},[
                                   dom('label',{'for': this.id + 'rymin'},[
                                       'y-range:'
                                   ])
                               ]),
                               dom('td',{},[
                                   this.rymin = dom('input',{'type': 'text', 'id': this.id + 'rymin', 'size': '5'}),
                                   this.rymax = dom('input',{'type': 'text', 'id': this.id + 'rymax', 'size': '5'})
                               ])
                           ]),
                           dom('tr',{},[
                               dom('td',{},[
                                   dom('label',{'for': this.id + 'select_format'},[
                                       'Format:'
                                   ])
                               ]),
                               dom('td',{},[
				   this.format = dom('select',{'id': this.id + 'select_format'})
                               ]),
                               dom('td',{},[
                                   this.downloadButton = dom('input',{'type': 'button', 'value': 'Download'})
                               ]),
                               dom('td')
                           ])
                       ])
                   ])
		])
	     );

	    // add format list
	    for (i=0; i<formats.length; i++) {
		$(this.format).append(dom('option',{'value': formats[i]},[this.mimetypes[formats[i]]]));
	    }
	    
	    $(this.downloadButton).click(function() {
		    var param = {
			xmin: parseFloat(that.rxmin.value),
			xmax: parseFloat(that.rxmax.value),
			ymin: parseFloat(that.rymin.value),
			ymax: parseFloat(that.rymax.value),
			height: parseInt(that.imageHeight.value,10),
			width: parseInt(that.imageWidth.value,10),
			format: that.format.value
		    };

		    that.events.triggerEvent('download',param);
		});

	    $(this.div).dialog({ autoOpen: false, width: 500});
	},

	open: function() {
	    var b = this.getCurrentExtent();

	    $(this.rxmin).attr('value',b.left);
	    $(this.rxmax).attr('value',b.right);
	    $(this.rymin).attr('value',b.bottom);
	    $(this.rymax).attr('value',b.top);

	    $(this.div).dialog('open');
	    
	}

    });

// Layer with UI elements
OceanBrowser.UI.Layer = EarthGL.Class({
	layer: null,
	info_dialog: null,

	initialize: function(id,layer) {
	    this.layer = layer;
	    this.info_dialog = OceanBrowser.UI.InfoLayer(layer);
	}
    });

OceanBrowser.UI.LayerList = EarthGL.Class(OceanBrowser.UI.BaseDialog,{
	$list: null,
	$controls: null,

	initialize: function(id) {
	    OceanBrowser.UI.BaseDialog.prototype.initialize.apply(this,[id + '_layer_list','Layer List']);

	    this.$list = $('<ul/>').attr({'class': 'LayerListList'});

	    this.$controls = $('<div/>').attr({'class': 'LayerListControls'})
	        .append($('<div/>')
			.append($('<div/>').attr({'class': 'FigurePropertiesConfig'}))
			.append($('<div/>').attr({'class': 'FigurePropertiesDownload'}))
			.append($('<div/>').attr({'class': 'FigurePropertiesInfo'}))
			.append($('<div/>').attr({'class': 'FigurePropertiesRemove'}))
			);

	    $(this.div).append($('<div/>').attr({'class': 'LayerListContainer'})
			       .append(this.$list)
			       .append(this.$controls));

	    this.$controls.find('.FigurePropertiesInfo').click(function() {
		    alert('toto');
		});
							       

	    $(this.div).dialog({ autoOpen: false, width: 300, height: 500});

	},

	add: function(layer) {
	    var depth = layer.get_dimension('elevation');
	    var time = layer.get_dimension('time');
	    var styles = layer.get_styles();
	    var j, $legend;
	    var $item = ($('<li/>').append($('<input/>').attr({'type': "radio", 
							       'name': 'LayerListRadio',
							       'checked': 'checked'}))
			 .append(layer.title));
	    
	    function add_dim(d,name) {
		if (d.range.length > 0) {
		    var $sel = $('<select/>').attr('title',name + ' [' + d.units + ']');
		    for (j=0; j < d.range.length; j++) {
			$sel.append($('<option/>').attr('selected',d.range[j] == d.default_value).append(d.range[j]));
		    }
		    $item.append($sel);
		}
	    }

	    add_dim(depth,'depth');
	    add_dim(time,'time');

	    $item.append($('<div/>').attr({'class': 'LegendButton','title':'Show or hide legend'})
			 .append($('<span/>').attr({'class': "ui-icon ui-icon-triangle-1-s"}))
			 .append($('<div/>')
				 .append('Legend')));

	    var legend;
	    legend = {url: 'http://localhost/web-vis-test/Python/web/wms?&amp;request=GetLegendGraphic&amp;width=200&amp;height=80&amp;transparent=true&amp;decorated=true&amp;style=cmap%3Ajet%2Binverted%3Afalse%2Bmethod%3Apcolor_flat%2Bvmin%3A-1.61687%2Bvmax%3A29.1772%2Bncontours%3A40&amp;color=%23000000&amp;format=image%2Fpng&amp;layer=Atlantic%2FTemperature.19752005.4Danl.nc%23Temperature_L1',
		      width: 200,
		      height: 80};
	    
	    var $legendContainer = $('<div/>').attr({'class': 'LayerListLegend'})
	    .append($('<div/>').css({'background-image': 'url(' + legend.url + ')',
								 'width': 200,
				     'height': 80}));
	    

	    $item.append($legendContainer);
		    
	    // call-back for showing/hiding legend
	    $item.find('.LegendButton').click(function() {
		    $legendContainer.toggle("slow");
		    $(this).find('.ui-icon').toggleClass("ui-icon-triangle-1-e");
		    $(this).find('.ui-icon').toggleClass("ui-icon-triangle-1-s");

		});

	    this.$list.append($item);
	    
	},

	open: function() {
	    $(this.div).dialog('open');
	}

    });

OceanBrowser.UI.AddLayer = EarthGL.Class(EarthGL.Control, {
	type: EarthGL.Control.TYPE_BUTTON,
	title: 'add layer',
	layerWMS: null,

	initialize: function(id,viewer,servers,baselayer) {
	    this.chooseLayer = new OceanBrowser.UI.chooseLayer(id,servers,baselayer);
	    this.chooseLayer.events.register('layerSelected', viewer, viewer.addLayer);
	},

	trigger: function() {
	    this.chooseLayer.open();
	},


	CLASS_NAME: "AddLayer"
    });


/**
 *	@class OceanBrowser user-interface
 */

OceanBrowser.UI.viewer3D = function(id,options) {
    this.map = null;
    this.mapid = id;

    this.layers = [];
    this.layer_num = 0;
    // ugly !!! needed for AnimLayer
    this.analysis_wms = {};
    this.figprops = {};
    this.rotating = false;
    this.fp = [];
    this.servers = SERVERS;
    this.previewBaselayer = null;

    var topoWidth = 64;
    var topoHeight = 32;


    this.events = new EarthGL.Events(this);

    EarthGL.Util.merge(this,options);

    var hmin = -8043.02;
    var hmax = 5472.27;

    var baseurl = '.';

    var topoLayer = new EarthGL.Layer('gebco_30sec_100.nc', 
				baseurl + '/Python/web/wms',
				{layers: 'gebco_30sec_100.nc#bat',
				 styles: 'cmap:gray+method:pcolor_flat+vmin:-8043.02+vmax:5472.27'
				});


    var topo = new EarthGL.Topo(64,32,hmin,hmax,topoLayer);
    this.map = new EarthGL.Map(id,{topo: topo});
    //this.map = new EarthGL.Map(id,{topo: topo, vscale: 1});

    this.map.addControl(new EarthGL.Control.Config('EarthGL/images/'));
    this.map.addControl(new EarthGL.Control.Rotate());
    this.map.addControl(new EarthGL.Control.Navigation());
    this.map.addControl(new EarthGL.Control.CameraPosition());

    this.addLayerControl = new OceanBrowser.UI.AddLayer(id + '-AddLayerControl',
							this,this.servers,this.previewBaselayer);

    this.map.addControl(this.addLayerControl);

    this.colorbar_container = document.getElementById('colorbar_container');


    var baselayer = new EarthGL.Layer('NASA Blue Marble', 
				      baseurl + '/Python/web/bluemarble',
				      {layers: 'BMNG'}, 
				      {isBaseLayer: true});

    

    this.map.addLayer(baselayer);
    this.map.setCenter(10,40);
};


/*
OceanBrowser.UI.viewer3D.prototype.removeLayer = function(field) {
    field.figprops.remove();

    this.map.removeLayer(field.layer);
};
*/

OceanBrowser.UI.viewer3D.prototype.downloadLayer = function(field) {

};

// obsolete
OceanBrowser.UI.viewer3D.prototype.get_wms_layer = function(id,param) {
    return this.figprops[id].getLayer(param);
};

OceanBrowser.UI.viewer3D.prototype.addLayer = function(obj) {
    var field = obj.field;
    var constraints = obj.constraints;

    
    var param = {};
    var wms_url;
    this.layer_num = this.layer_num+1;    

    if (constraints.type === 'lon-lat') {
	wms_url = field.wms_url;	    
    }
    else {
	param.section = Util.encodesec(constraints.lon,constraints.lat);	
	console.log('adding ' + field.title + ' ' + field.name,param.section);
	wms_url = 'Python/web/wms_vert?';
    }    

    console.log('adding ' + field.title + ' ' + field.name,constraints.lat);
    
    var that = this;
    var remove_callback = function() {
	// this is an instance of FigureProperties
	console.log('removing ' + this.Layer.title + ' ' + this.Layer.name);
	that.map.removeLayer(this.layerWMS);
	this.remove();
    };

    var download_callback = function() {
	// that.downloadLayer(field);
    };


    var figprops = new FigureProperties(this.mapid,this.mapid + this.layer_num,
				    wms_url,
				    function() { 
					console.log('update field ' + field.title + ' ' + field.name);					
					that.map.removeLayer(figprops.layerWMS);
					figprops.loadStat(param);
				    },
       {colorbarclass: 'colorbar2',
        colorbar_container: this.colorbar_container,
        title: field.title,
	Layer: field,
	abstract_info: field.abstract_info,
        metadata_url: field.metadata_url,
        add_style_button: true,
	download_callback: download_callback,
        remove_callback: remove_callback,
        constraints: constraints});
    

    // ugly !!! needed for AnimLayer
    this.figprops[field.id] = figprops;


    if (constraints.type == 'lon-lat') {
	// query depth dimension and add to dialog if appropriate

	var depths = field.get_dimension('elevation');

	if (depths.range.length > 0) {
	    figprops.set_dimension('elevation','depth',depths);
	}
    }


    // query time dimension and add to dialog if appropriate

    var time = field.get_dimension('time');

    if (time.range.length > 0) {	
	figprops.set_dimension('time','time',time);
	
	figprops.anim = new AnimLayer(figprops.button_anim,
				      figprops.dimensions['time'].sel,
				      this,field.id);
	
    }

    // update button

    var button_update = document.createElement("input");
    button_update.type = "button";
    button_update.value = "Update";
    figprops.layer_info_div.appendChild(button_update);	
    $(button_update).click(function() {
	    that.map.removeLayer(figprops.layerWMS);
	    figprops.loadStat(param);
	});
    figprops.button_update = button_update;

    figprops.onload = function() {
	figprops.layerWMS = figprops.getLayer();

	// ugly !!! needed for AnimLayer
	that.analysis_wms[field.id] = figprops.layerWMS;
	that.map.addLayer(figprops.layerWMS);
	console.log('loaded ' + field.title + ' ' + field.name);
	that.events.triggerEvent('fieldadded',{field: field});
    };

    figprops.loadStat(param);
    this.fp.push(figprops);
};


OceanBrowser.UI.LayerTree = function(id,url,options) {
    this.id = id;
    this.url = url;
    this.params = '';
    // four digit random number
    this.namespace = 'layer_list_' + Math.floor(Math.random()*1e4);
    this.elem = null;
    this.choose_multiple = true;
    this.show_title = false;

    this.version = '1.3.0';
    this.extra_param = {};
    this.use_proxy = null;
    this.requests = [];
    this.WMS_extensions = 'OceanBrowser';

    // options
    if (options) {
	for (var p in options) {
	    this[p] = options[p];
	}
    }

    this.events = new EarthGL.Events(this);

    // linear list of all layers
    this.layer_infos = [];
    this.current_leave = null;
};

// methods
OceanBrowser.UI.LayerTree.prototype.load = function() {
    var cap = document.getElementById(this.id);

    if (!this.elem) {
	this.elem = document.createElement("div");
	cap.appendChild(this.elem);
    }

    Util.removeChildNodes(this.elem);
    
    var img = document.createElement("img");
    img.src = "img/ajax-loader.gif";
    img.alt = "loading";
    this.elem.appendChild(img);
    this.elem.appendChild(document.createTextNode("Loading..."));

    // default parameters for request
    var params = {
	request: "GetCapabilities",
	service: "WMS",
	version: this.version
    };

    // over-write with extra parameter for request
    for (var p in this.extra_param) {
	params[p] = this.extra_param[p];
    }

    // use proxy instead of real WMS server
    //console.log('lala ',Util.append_param(this.url,params));    

    Util.proxy_ajax(this.url, params, this, this.make_tree, {proxy: this.use_proxy});
};

OceanBrowser.UI.LayerTree.prototype.make_tree = function(xmldoc) {
    var elem, url;

    this.xmldoc = xmldoc;

    // remove 'Loading...' message
    Util.removeChildNodes(this.elem);

    // service
    var service = xmldoc.getElementsByTagName('Service')[0];
    var item = service.firstChild;
    
    while (item !== null) {
	if (item.tagName == "Title" && item.firstChild) {
	    this.title = item.firstChild.data;
        }
        else if (item.tagName == "Abstract" && item.firstChild) {
	    this.abstract_info = item.firstChild.data;
        }
        item = item.nextSibling;         
    }

    // all requests
    var req = xmldoc.getElementsByTagName('Request')[0];
    item = req.firstChild;    
    while (item !== null) {
	if (item.tagName) {
	    var requestInfo = {formats: []};

	    var item2 = item.firstChild;
	    while (item2 !== null) {
		if (item2.tagName == "Format" && item2.firstChild) {
		    requestInfo.formats.push(item2.firstChild.data);
		}

		item2 = item2.nextSibling;
	    }

	    this.requests[item.tagName] = requestInfo;
	}
  	item = item.nextSibling;             
    }


    // get the url for GetMap requests
    var GetMap = xmldoc.getElementsByTagName('GetMap');

    if (GetMap.length > 0) {
	var get = GetMap[0].getElementsByTagName('Get');
	if (get.length > 0) {	
	    elem = get[0].getElementsByTagName("OnlineResource")[0];

	    if (elem.getAttributeNS) {
		var xlinkns = "http://www.w3.org/1999/xlink";
		url = elem.getAttributeNS(xlinkns,"href");
	    }
	    else {
		// IE
		url = elem.getAttribute("xlink:href");
	    }	    

	    //console.log("url ",url);
	    this.url = url;	    
	}
    }

    // show title

    if (this.show_title) {    
	var title_elem = document.createElement("h2");
	title_elem.appendChild(document.createTextNode(this.title));
	//this.elem.appendChild(title_elem);
	this.elem.parentNode.insertBefore(title_elem,this.elem);
    }

    // layer inventory
    var root = xmldoc.getElementsByTagName('Capability')[0];
    this.list = this.layer_list(root);

    this.elem.appendChild(this.list);

    // jsTree configuration
    var that = this;

    var config = { 	    
	types: {
	    valid_children: [ "folder" ],
	    types: {
		'folder' : {
		    icon: { 
			image: "img/drive.png" 
		    },
		    hover_node: false,
		    select_node: function (node) { 
			if (this.is_closed(node)) {
			    this.open_node(node);
			}
			else {
			    this.close_node(node);
			}

			return false;
		    }		
		},
	        'default': {
		    select_node : function (node,tree,event) { 
			//does not work in IE
			//var i = parseInt($(node).attr('name'),10);			
			// strip namespace cand convert to number
			var id;

			// jsTree 1.0-rc1
			id = node.id;
			
			if (!id) {
			    // jsTree 1.0-rc3
			    id = node.find('a').attr('id');
			}

			var i = parseInt(id.replace(that.namespace,''),10);
			var Layer = that.layer_infos[i];
			console.log('click ',Layer,this.is_selected (node),'event',event);
			
			if (this.is_selected (node)) {
			    that.events.triggerEvent('layerDeselected',Layer);  
			    //that.deselectLayer(Layer);
			}
			else {
			    that.events.triggerEvent('layerSelected',Layer);  
			    //that.selectLayer(Layer);
			}
			
			return true;
		    } 
		    /*deselect_node : function (node,tree) { 
			var i = parseInt($(node).attr('name'),10);
			var Layer = that.layer_infos[i];
			//that.events.triggerEvent('layerDeselected',Layer);  
			console.log('lala ',Layer);
			return true;
			}*/

	        }
	    }
	},
	plugins: ["themes","html_data","ui","types"]
    };

    if (this.choose_multiple) {
	config.ui = {select_multiple_modifier: "on"};
    }
    else {
	config.ui = {select_limit: 1};
    }

    $(this.elem).jstree(config);

    this.events.triggerEvent('loaded',this);           
};    

OceanBrowser.UI.LayerTree.prototype.layer_list = function(root) {
    var that = this;
    var item = root.firstChild;
    var list = document.createElement("ul");

    var elem, i = 0;

    var vert_wms_url = null;
    if (this.WMS_extensions == 'OceanBrowser') {
	// replace wms by wms_vert for the WMS server 
	// providing vertical sections
	vert_wms_url = this.url.replace(/\/wms\b/,'/wms_vert');
    }

    while (item !== null) {
	if (item.tagName == "Layer") {
	    var Layer = new LayerInfo(item, 
				      {wms_url: this.url, 
				       vert_wms_url: vert_wms_url,
				       use_proxy: this.use_proxy,
				       WMS_extensions: this.WMS_extensions,
				       cap: this
				      }
				      );


	    var layer_num = this.layer_infos.length;
	    this.layer_infos.push(Layer);

	    var list_item = document.createElement("li");

	    var sub = this.layer_list(item);

	    if (sub.childNodes.length === 0) {
		// leave

		elem = document.createElement("a");
		elem.href = '#';
		elem.name = '' + layer_num;
		elem.id = this.namespace + layer_num;
		elem.title = Layer.title;
		
		elem.appendChild (document.createTextNode(Layer.title));
		list_item.appendChild(elem);
	    }
	    else {
		// tree
		list_item.setAttribute('rel','folder');

		elem = document.createElement("a");
		elem.href = '#';
		elem.appendChild(document.createTextNode(Layer.title));

		list_item.appendChild(elem);

		list_item.appendChild(sub);
	    }
	    

	    list.appendChild(list_item);	    
	}

	item = item.nextSibling; 
    }


    return list;
};


OceanBrowser.UI.LayerTree.prototype.getNode = function(layer) {
    for (var i=0; i < this.layer_infos.length; i++) {
	if (this.layer_infos[i] == layer) {
	    return document.getElementById(this.namespace + i);
	}
    }

    return null;
};

// mark the specifed layer as selected and trigger the layerSelected event

OceanBrowser.UI.LayerTree.prototype.selectLayer = function(layer) {
    $(this.elem).jstree('select_node',this.getNode(layer));
};

// mark the specifed layer as deselected and trigger the layerDeselected event

OceanBrowser.UI.LayerTree.prototype.deselectLayer = function(layer) {
    $(this.elem).jstree('deselect_node',this.getNode(layer));
    // event is not tiggered in jsTree, so trigger it now
    this.events.triggerEvent('layerDeselected',layer);  
};



