/******************************************************************************
 *                                                                            *
 *  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/>.     *
 *                                                                            *
 ******************************************************************************/


// TODO: remove section_name

function log(message) {
    document.getElementById("log").firstChild.data += "" + message + "\n";
}


// VerticalSection extends anim class

VerticalSection.prototype = new anim();
VerticalSection.prototype.constructor = VerticalSection;

function VerticalSection() {
    anim.call(this,
	      "vert_map",
	      document.getElementById('vert_map_colorbars')
	      );

    this.control = null;
    this.xaxis = new Axis("xaxis","x",{tickslabelclass: "xtickslabel", ticksclass: "xticks"});
    this.yaxis = new Axis("yaxis","y",{tickslabelclass: "ytickslabel", ticksclass: "yticks"});
    this.ratio = 1/100;
    this.vectors = null;
    this.map_selection = null;
    this.mini_wms = {};
    this.mini_baselayer_wms = null;
    this.analysis_wms = {};
    this.Layers = {};
    this.map = null;
    this.wms_url = "Python/web/wms_vert?";
    this.section = '';

    var scale = 1;

    var xmin = 0/(scale*this.ratio); 
    var xmax = 120/(scale*this.ratio);
    var ymin = -10000/(scale);
    var ymax = 360/(scale);

    if (this.map) {
	this.map.destroy();
    }
    
    if (this.map_selection) {
	this.map_selection.destroy();
    }

    this.map_selection = new OpenLayers.Map("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]
    };

    this.mini_baselayer_wms = new OpenLayers.Layer.WMS("Continents",baselayer_url, 
						       {layers: baselayer_name, 
							format: baselayer_format},
						       options);

    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.addLayers([this.mini_baselayer_wms,this.vectors]);
    this.vectors.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);

    this.map_selection.addControl(this.control);
    
    var obj = this;
    // how to prevent default action such as selection (in Chrome) 
    // after featureadded event?
    this.vectors.events.register("featureadded", null, function(event) { obj.update(); });
    
    var bounds = new OpenLayers.Bounds(xmin,ymin,xmax,ymax);

    this.map = new OpenLayers.Map('vert_map', {
	    projection: "EPSG:4326" ,
	    maxExtent: bounds,
	    numZoomLevels: 70,
	    //	    maxScale: 2,
	    maxResolution: 10000/256, // maximum depth / height of map 
	    units: 'm',
	    theme: null
                });

    this.map.events.register("dragend", null, function() { obj.draw_axis(); });
    this.map.events.register("moveend", null, function() { obj.draw_axis(); });
    this.map.events.register("zoomend", null, function() { obj.draw_axis(); });


    this.baselayer = new OpenLayers.Layer.WMS( "Base layer",
					       "img/blank.gif?", {layers: 'BMNG',
								   format: 'image/png'},
					{isBaseLayer: true});

    this.map.addLayers([this.baselayer]);
    
    this.map.addControl(new OpenLayers.Control.LayerSwitcher());
    this.map.addControl(new OpenLayers.Control.CustomNavToolbar(this));
 
    //alert(bounds);
    this.map.fractionalZoom = true;

    //document.getElementById("ratio").value = this.ratio;


}


VerticalSection.prototype.addLayer = function(Layer) {
    anim.prototype.addLayer.call(this,Layer);
    var id = Layer.id;    

    var display_param = hsection.get_layer_param(id);
    console.log(display_param.style);

    this.change_select_section(document.getElementById("select_section"));
	
    this.mini_wms[id] = new OpenLayers.Layer.WMS(Layer.title,
						 "Python/web/wms",
					     {layers: decodeURIComponent(Layer.name), styles: display_param.style,
					      transparent: "true", format: "image/png"});

    this.mini_wms[id].mergeNewParams(display_param.param);
    this.map_selection.addLayer(this.mini_wms[id]);
    // make sure that mini_wms is under the vector layer
    this.mini_wms[id].setZIndex(this.map_selection.Z_INDEX_BASE.BaseLayer + this.layer_num);

    // query time dimension and add to dialog if appropriate

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

    if (time.range.length > 0) {	

	this.figprops[id].set_dimension('time','time',time);

	this.Layers[id].anim = new AnimLayer(
					     this.figprops[id].button_anim,
					     this.figprops[id].dimensions['time'].sel,
					     this,id);
    }


    // if section is already defined request the same sector for the variable
    if (this.section) {
	this.request_section(id);
    }
};



VerticalSection.prototype.removeLayer = function(Layer) {
    anim.prototype.removeLayer.call(this,Layer);
    var id = Layer.id;    

    this.map_selection.removeLayer(this.mini_wms[id]);
    if (this.analysis_wms[id]) {
		this.map.removeLayer(this.analysis_wms[id]);
    }

    delete this.mini_wms[id];
    delete this.analysis_wms[id];
};

VerticalSection.prototype.onvisible = function() {


    if (this.map_selection) {
	console.log("width: " +    $(this.map_selection.div).width());
    }
    var bounds = this.get_bounds();
    //alert("hor bounds: " + bounds);
    //this.map.zoomToExtent(bounds);

    var ms = this.map_selection;

    // can only zoomToExtent when maps is visible
    // is there a better way????
    timeout = setTimeout(function () { 
	    //console.log("bounds cb: " + bounds);
	    //console.log("width: " +    $(ms.div).width());
		
	    //alert("bounds cb: " + bounds);
		ms.zoomToExtent(bounds,true);
		 },1000);

};

VerticalSection.prototype.draw_axis = function() {
    //alert("vert_map.maxExtent " + this.map.getExtent());
    var b = this.map.getExtent();


    this.xmin = b.left*this.ratio; 
    this.xmax = b.right*this.ratio;
    this.ymin = b.bottom;
    this.ymax = b.top;

    this.xaxis.set_range(this.xmin,this.xmax);
    this.yaxis.set_range(this.ymin,this.ymax);

    document.getElementById("xmin").value = "" + this.xmin;
    document.getElementById("xmax").value = "" + this.xmax;
    document.getElementById("ymin").value = "" + this.ymin;
    document.getElementById("ymax").value = "" + this.ymax;
};



VerticalSection.prototype.clear_map_selection = function(event) {
	this.vectors.destroyFeatures();
};

VerticalSection.prototype.request_section = function(id,time) {
    var obj = this;

	    if (this.Layers[id].WMS_extensions == 'OceanBrowser') {

		vtime = time;

		// default value of time
		if (vtime === undefined) {
		    vtime = this.figprops[id].get_dimension('time');
		}


		var Layer = this.Layers[id];
		
		var params  = {section: this.section,
			       layer: decodeURIComponent(Layer.name),
			       time: vtime,
			       request: "GetStats"};

		// closure around id
		var fun = function(id) {
		    return function(xmldoc) { 
			obj.stat(xmldoc,id);
		    };
		}(id);
		    
		Util.proxy_ajax(this.Layers[id].vert_wms_url,params,null,fun,{proxy: this.Layers[id].use_proxy});  
	    }

};

VerticalSection.prototype.update = function(time) {
    var vtime;

    // make sure that path is visible
    this.vectors.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);
    var c = this.vectors.features[this.vectors.features.length-1].geometry.components;
    var section = "";
    for (var i=0; i < c.length; i++) {
	section += c[i].x + "," + c[i].y + "|";
    }
    this.section = section.substring(0,section.length-1);

    // test if section was choosen
    if (this.section) {
	document.getElementById("status").firstChild.data = "Extract section...";

	for (var id in this.Layers) {
	    this.request_section(id,time);
	}
    }
};

VerticalSection.prototype.stat = function(xmldoc,id) {
    this.data_xmin = parseFloat(xmldoc.getElementsByTagName("xmin")[0].firstChild.nodeValue);
    this.data_xmax = parseFloat(xmldoc.getElementsByTagName("xmax")[0].firstChild.nodeValue);
    this.data_ymin = parseFloat(xmldoc.getElementsByTagName("ymin")[0].firstChild.nodeValue);
    this.data_ymax = parseFloat(xmldoc.getElementsByTagName("ymax")[0].firstChild.nodeValue);


    document.getElementById("xmin").value = "" + this.data_xmin;
    document.getElementById("xmax").value = "" + this.data_xmax;
    document.getElementById("ymin").value = "" + this.data_ymin;
    document.getElementById("ymax").value = "" + this.data_ymax;

    this.figprops[id].set_stat(xmldoc);

    document.getElementById("status").firstChild.data = "";

    this.update_layer(id);
};

VerticalSection.prototype.get_wms_layer = function(id,options) {
    var Layer = this.Layers[id];
    var time = this.figprops[id].get_dimension('time');


    // default parameter values
    var analysis_params = {layers: decodeURIComponent(Layer.name),
			   styles: this.figprops[id].get_style(),
			   format: 'image/png', 
			   transparent: "true", 
			   ratio: this.ratio,
			   section: this.section,
			   time: time
    };


    // override by parameters in options
    for (var key in options) {
	analysis_params[key] = options[key];
    }


    var layer = new OpenLayers.Layer.WMS(Layer.title,this.Layers[id].vert_wms_url,
					 analysis_params,	
                                         {isBaseLayer: false});

    return layer;
};

VerticalSection.prototype.update_all = function() {
    for (var id in this.Layers) {
	this.update_layer(id);
    }
};

VerticalSection.prototype.update_layer = function(id) {
    // do nothing if section was not created
    if (this.section.length === 0) {
	alert('Please draw a section first.');
	return;
    }

    this.xmin = parseFloat(document.getElementById("xmin").value);
    this.xmax = parseFloat(document.getElementById("xmax").value);
    this.ymin = parseFloat(document.getElementById("ymin").value);
    this.ymax = parseFloat(document.getElementById("ymax").value);


    //var depth_range = parseFloat(document.getElementById("ratio").value);
    var map_height = $('#vert_map').height();
    var map_width = $('#vert_map').width();

    this.ratio = (this.xmax-this.xmin)/(this.ymax-this.ymin) * map_height/map_width;
    this.bounds = new OpenLayers.Bounds(this.xmin/this.ratio,this.ymin,this.xmax/this.ratio,this.ymax);

    //this.map.maxExtent = new OpenLayers.Bounds(this.data_xmin/this.ratio,this.data_ymin,this.data_xmax/this.ratio,this.data_ymax);



    if (!(id in this.analysis_wms)) {
	    this.analysis_wms[id] = this.get_wms_layer(id);

	    this.map.addLayers([this.analysis_wms[id]]);

	    //draw_axis();
    }
    else {
	    var time = this.figprops[id].get_dimension('time');
	    var analysis_params = {layers: decodeURIComponent(this.Layers[id].name),
				   styles: this.figprops[id].get_style(),
				   format: 'image/png', 
				   transparent: "true", 
				   ratio: this.ratio,
				   section: this.section,
				   time: time};
	    
	    this.analysis_wms[id].mergeNewParams(analysis_params);
	    this.analysis_wms[id].redraw();
    }


    this.map.zoomToExtent(this.bounds,true);
    this.draw_axis();    
};

VerticalSection.prototype.change_select_section = function(element) {
    if (element.checked) {
	this.control.activate();
	// this.control.handler.layer is a temporary drawing layer
	// make sure it is visible
	this.control.handler.layer.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);
    }
    else {
	this.control.deactivate();
    }

    // make sure that path is visible
    this.vectors.setZIndex(this.map_selection.Z_INDEX_BASE.Feature);
};


VerticalSection.prototype.getCurrentExtent = function() {
    var b = this.map.getExtent();
    b.left = b.left*this.ratio; 
    b.right = b.right*this.ratio;

    return b;
};


// download current view

VerticalSection.prototype.download = function(id,opt) {
    // same extend as current view

    var extent = this.analysis_wms[id].getExtent();
    var b = this.map.getExtent();
    this.xaxis.set_range(b.left*this.ratio,b.right*this.ratio);

    var time = this.figprops[id].get_dimension('time');

    // # axis leaves some room for labels and colorbar
    // self.ax = self.fig.add_axes([0.1, 0.1, 0.7, 0.8])
    // choose ratio fill all space

    var ratio = (opt.xmax-opt.xmin)/(opt.ymax-opt.ymin) * (0.8*opt.height)/(0.7*opt.width);

    var style = this.figprops[id].get_style();
    var bounds = new OpenLayers.Bounds(opt.xmin/ratio,opt.ymin,opt.xmax/ratio,opt.ymax);

    var params = 
      {layers: decodeURIComponent(this.Layers[id].name),
       section: this.section,
       request: "GetMap",
       width: opt.width,
       height: opt.height,
       bbox: bounds.toBBOX(),
       transparent: true,
       decorated: true,
       styles: style,
       /*cmap: this.figprops[id].get_colormap(),*/
       format: opt.format,
       ratio: ratio,
       time: time
      };

    var url = Util.append_param(this.Layers[id].vert_wms_url,params);

    window.open(url,'Image');
};

