/**
 *  ****************************************************************************
 *  File : design/previmer/javascript/previmer_geoitem.js
 *  vers : 1.1
 *  build: 20070731
 *  Author : Virtualys
 *  ****************************************************************************
 **/

/**
 * ============================================================================= 
 * GeoItem
 * Classe abstraite de tous les éléments géolocalisés.
 * ============================================================================= 
 */ 
GeoItem = function(domNode)
{
	// Identifiant de l'item
	this._id = $(domNode).attr('id');
	// Item par défaut
	this._default = $(domNode).attr('default') == 'true';
	// Emprise contenant cet item
	this._area = $(domNode).attr('area');
	// Label de l'item
	this._label = null;

	// Coordonnées pixels des points
	this._coords = [];
	// Coordonnées géo des points
	this._geocoords = [];
	// Identifiant interne unique
	this._itemId = 1;
	// Noeud HTML <area> contenant une map calculée à partir des coordonnées pixels
	this._htmlAreaNode = null;
}
/**
 * -----------------------------------------------------------------------------
 * Obtient un noeud HTML area correspondant à une image map de cet élément.
 * @param ratio (s'il est positionné à object, alors les coordonnées sont calquées
 * sur la taille de l'image vignette, sinon tableau ratioX, ratioY)
 * @param index de l'élément à sélectionner
 * @return le noeud area   
 */
GeoItem.prototype.getAreaMap = function(ratio, index, appCfg)
{
	this._htmlAreaNode= $('<area/>');
	if( this._id )
		this._htmlAreaNode.attr('id', this._id);
	if( index != -1 )
	{
		var link = !appCfg ? this._computeLink(index) : this._computeLink(null,appCfg);
		this._htmlAreaNode.attr('href', link);
	}
	if (this._label)
	{
		this._htmlAreaNode.attr('alt', HtmlDecode(this._label));
		this._htmlAreaNode.attr('title', HtmlDecode(this._label));
	}
	if (ratio instanceof Array) {
		var coords = this._getAreaCoords(ratio);
	}
	else {
		var width = ratio.width();
		var height = ratio.height();
		var coords = "0 0 0 " + height + " " + width + " " + height + " " + width + " 0";
	}
	this._htmlAreaNode.attr('shape', this._getAreaType());
	this._htmlAreaNode.attr('coords', coords);
	
	return this._htmlAreaNode;
}
// -----------------------------------------------------------------------------
GeoItem.prototype._computeLink = function(index,appCfg) {
	var geoLink = null;
	if (!appCfg)
		geoLink = "javascript:browser.getCBManager().onSelectGeoItem('" + index + "', true)";
	else
	{
		geoLink=appCfg.appLink;
		geoLink+= '/(typevisu)/' + appCfg.config.visu;
		geoLink+= '/(zoneid)/' + this._area;
		geoLink+= '/(geoid)/' + this._id;
		geoLink+= '#appTop';
	}
	return geoLink;
}
/**
 * -----------------------------------------------------------------------------
 * Ajoute un point à la description géométrique de l'élément.
 * @param lon longitude du point à rajouter 
 * @param lat latitude du point à rajouter 
 * @param x X en pixels du point 
 * @param y Y en pixels du point 
 */
GeoItem.prototype._pushCoord = function(lon, lat, x, y)
{
	this._geocoords.push(
			{ 'lon' : parseFloat(lon),
				'lat' : parseFloat(lat) });
	this._coords.push(
			{ 'x' : parseInt(x, 10),
				'y' : parseInt(y, 10) });
	lon = Math.round(lon * 100000);
	lat = Math.round(lat * 100000);
	this._itemId = 31 * this._itemId + (lon ^ (lon >>> 32));
	this._itemId = 31 * this._itemId + (lat ^ (lat >>> 32));
}
/**
 * -----------------------------------------------------------------------------
 * Obtient une description des points composant cet élément.
 * @return une chaîne contenant la liste des coordonnées
 */  
GeoItem.prototype._dumpCoords = function()
{
	var str = '[';
	for (var i = 0; i < this._geocoords.length; ++i)
	{
		if (i != 0)
		{ str += ', '; }
		str +=
			PrevimerToolkit.toDMS(this._geocoords[i].lat, false) + ', ' +
			PrevimerToolkit.toDMS(this._geocoords[i].lon, true);
	}
	return str + ']';
	}
/**
 * -----------------------------------------------------------------------------
 * Obtient une représentation texte de l'élément.
 * @return une chaîne contenant la description
 */  
GeoItem.prototype.toString = function()
{
	return this._dumpCoords();
}

/**
 * ============================================================================= 
 * PolygonGeoItem
 * Elément de type polygone.
 * ============================================================================= 
 */ 
PolygonGeoItem = function(domNode)
{
	PolygonGeoItem.superConstructor.call(this, domNode);
	var that = this;
	var vertices = $('vertex', domNode).each( function(i){
		that._pushCoord($(this).attr('lon'),
				$(this).attr('lat'),
				$(this).attr('x'),
				$(this).attr('y')
		);
	});
}
PrevimerToolkit.inherits(PolygonGeoItem, GeoItem);
/**
 * -----------------------------------------------------------------------------
 * Obtient le type de l'élément.
 * @return le type
 */  
PolygonGeoItem.prototype._getAreaType = function()
{
	return 'poly';
}
/**
 * -----------------------------------------------------------------------------
 * Obtient une représentation texte de l'élément.
 * @return une chaîne contenant la description
 */  
PolygonGeoItem.prototype.toString = function()
{
	return 'polygon ' + PolygonGeoItem.superClass.toString.call(this);
}
/**
 * -----------------------------------------------------------------------------
 * Obtient les coordonnées à utiliser au sein de la balise HTML area.
 * @param ratio facteur d'échelle à appliquer
 * @return une chaîne contenant les coordonnées au bon format
 */  
PolygonGeoItem.prototype._getAreaCoords = function(ratio)
{
	var vertices = '';
	var rnd = Math.round;
	for (var i = 0; i < this._coords.length; ++i)
	{
		if (i != 0) { vertices += ',' }
		with (this._coords[i])
		{
			vertices += rnd(ratio[0] * x) + ',' + rnd(ratio[1] * y);
		}
	}
	return vertices;
}

/**
 * ============================================================================= 
 * LineGeoItem
 * Elément de type segment.
 * ============================================================================= 
 */ 
LineGeoItem = function(domNode)
{
	LineGeoItem.superConstructor.call(this, domNode);
	this._pushCoord(
			$(domNode).attr('lon1'),
			$(domNode).attr('lat1'),
			$(domNode).attr('x1'),
			$(domNode).attr('y1'));
	this._pushCoord(
			$(domNode).attr('lon2'),
			$(domNode).attr('lat2'),
			$(domNode).attr('x2'),
			$(domNode).attr('y2'));
	this._label = $(domNode).attr('label');
}
PrevimerToolkit.inherits(LineGeoItem, GeoItem);
/**
 * -----------------------------------------------------------------------------
 * Obtient le type de l'élément.
 * @return le type
 */  
LineGeoItem.prototype._getAreaType = function()
{
	return 'line';
}
/**
 * -----------------------------------------------------------------------------
 * Obtient une représentation texte de l'élément.
 * @return une chaîne contenant la description
 */  
LineGeoItem.prototype.toString = function()
{
	return 'line ' + LineGeoItem.superClass.toString.call(this);
}
/**
 * -----------------------------------------------------------------------------
 * Obtient les coordonnées à utiliser au sein de la balise HTML area.
 * @param ratio facteur d'échelle à appliquer
 * @return une chaîne contenant les coordonnées au bon format
 */  
LineGeoItem.prototype._getAreaCoords = function(ratio)
{
	var rnd = Math.round;
	var width = 4;

	var x0 = this._coords[0].x;
	var x1 = this._coords[1].x;
	var y0 = this._coords[0].y;
	var y1 = this._coords[1].y;
	var dx = x1 - x0;
	var dy = y1 - y0;
	var angle = Math.atan2(dy, dx) + Math.PI / 2;
	dx = Math.cos(angle) * width;
	dy = Math.sin(angle) * width;
	if( dx > 0 )
		dx = Math.max(2, rnd(dx));
	else
		dx = Math.min(-2, rnd(dx));
	if( dx > 0 )
		dy = Math.max(2, rnd(dy));
	else
		dy = Math.min(-2, rnd(dy));

	var coords = '';
	coords += (rnd(ratio[0] * x0) + dx) + ',' + (rnd(ratio[1] * y0) + dy) + ',';
	coords += (rnd(ratio[0] * x0) - dx) + ',' + (rnd(ratio[1] * y0) + dy) + ',';
	coords += (rnd(ratio[0] * x1) - dx) + ',' + (rnd(ratio[1] * y1) - dy) + ',';
	coords += (rnd(ratio[0] * x1) + dx) + ',' + (rnd(ratio[1] * y1) - dy) + ',';
	coords += (rnd(ratio[0] * x0) + dx) + ',' + (rnd(ratio[1] * y0) + dy);
	return coords;
}

/**
 * ============================================================================= 
 * PointGeoItem
 * Elément de type point.
 * ============================================================================= 
 */ 
PointGeoItem = function(domNode)
{
	PointGeoItem.superConstructor.call(this, domNode);
	this._pushCoord(
			$(domNode).attr('lon'),
			$(domNode).attr('lat'),
			$(domNode).attr('x'),
			$(domNode).attr('y'));

	var label = $(domNode).attr('label');
	if (label != null)
	{
		this._label = label + ' (' +
			PrevimerToolkit.toDMS(this._geocoords[0].lon, true) +
			' ' + PrevimerToolkit.toDMS(this._geocoords[0].lat, false) + ')';
	}else
	{
		this._label = PrevimerToolkit.toDMS(this._geocoords[0].lon, true) + ' ' +
			PrevimerToolkit.toDMS(this._geocoords[0].lat, false);
	}
}
PrevimerToolkit.inherits(PointGeoItem, GeoItem);
/**
 * -----------------------------------------------------------------------------
 * Obtient le type de l'élément.
 * @return le type
 */  
PointGeoItem.prototype._getAreaType = function()
{
	return 'circ';
}
/**
 * -----------------------------------------------------------------------------
 * Obtient une représentation texte de l'élément.
 * @return une chaîne contenant la description
 */  
PointGeoItem.prototype.toString = function()
{
	return 'point ' + PointGeoItem.superClass.toString.call(this);
}
/**
 * -----------------------------------------------------------------------------
 * Obtient les coordonnées à utiliser au sein de la balise HTML area.
 * @param ratio facteur d'échelle à appliquer
 * @return une chaîne contenant les coordonnées au bon format
 */  
PointGeoItem.prototype._getAreaCoords = function(ratio)
{
	var coords =
		Math.round(ratio[0] * this._coords[0].x) + ',' +
		Math.round(ratio[1] * this._coords[0].y) + ',6';
	return coords;
}

/**
 * ============================================================================= 
 * AreaGeoItem
 * Elément de type Emprise.
 * ============================================================================= 
 */ 
AreaGeoItem = function(domNode)
{
	var geomNode = $(domNode).children('shape');
	AreaGeoItem.superConstructor.call(this, geomNode);

	this._id = $(domNode).attr('id');
	this._label = $(domNode).attr('label');
	if ($(domNode).attr('z-index'))
	{
		this._zIndex = parseInt($(domNode).attr('z-index'));
	}
	else
	{
		this._zIndex = 0;
	}
	this._areas = [];
	var that = this;
	$(domNode).children('children').each(function(i){
		$(this).children('area').each(function(j){
			var area = new AreaGeoItem(this);
			area._area = that._id;
			that._areas.push(area);
		});
	});
}
PrevimerToolkit.inherits(AreaGeoItem, PolygonGeoItem);
/**
 * -----------------------------------------------------------------------------
 * Obtient une représentation texte de l'élément.
 * @return une chaîne contenant la description
 */  
AreaGeoItem.prototype.toString = function()
{
	return 'area ' + AreaGeoItem.superClass.toString.call(this);
}
AreaGeoItem.prototype.getArea = function(areaID)
{
	if (this._id == areaID) {
		return this;
	}
	for (var i = 0; i < this._areas.length; ++i)
	{
		var area = this._areas[i].getArea(areaID);
		if (area)
		{
			return area;
		}
	}
	return null;
}
AreaGeoItem.prototype._computeLink = function(index, appCfg)
{
	var geoLink = null;
	if (!appCfg)
		geoLink = "javascript:browser.getCBManager().onSelectArea('" + index + "', true)";
	else
	{
		geoLink=appCfg.appLink;
		geoLink+= '/(typevisu)/' + appCfg.config.visu;
		geoLink+= '/(zoneid)/'+this._id;
		geoLink+= '#appTop';
	} 
	return geoLink;
}

ShapeRegistry = {
	'shape' : PolygonGeoItem.prototype.constructor,
	'line'  : LineGeoItem.prototype.constructor,
	'point' : PointGeoItem.prototype.constructor
};
/**
 *  ****************************************************************************
 *  File : design/previmer/javascript/previmer_resulttype.js
 *  vers : 1.1
 *  build: 20070731
 *  Author : Virtualys
 *  ****************************************************************************
 **/

/**
 * ============================================================================= 
 * ResultType
 * Type de résultat (image, courbe, spectre ...)
 * ============================================================================= 
 */ 
ResultType = function(domNode, variable)
{
	// Identifiant du type
	this.id = $(domNode).attr('type');
	// Eléments géométriques associés
	this.geoItems = { };
	// Eléments par défaut en fonction des emprises
	this.defaultGeoItem = { };
	// Niveaux
	this.depths = { };
	// Formats (image, flash, ...)
	this.formats = [ ];
	// Eléments temporels
	this.timeConfig = null;
	// Animations
	this.animations = null;
	// Variable contenant ce type de résultat
	this.variable = variable;
		
	// Initialisation
	var that = this;
	var coverageNodes = $('coverage', domNode).children().each(function(i)
		{
			var geoItem = new ShapeRegistry[this.tagName](this);
			that.geoItems[geoItem._area + "_" + geoItem._id] = geoItem;
			if (geoItem._default || that.defaultGeoItem[geoItem._area] == undefined)
			{
				that.defaultGeoItem[geoItem._area] = geoItem;
			}
		});
	var timeConfigNode = $('timeconfig', domNode);
	if (timeConfigNode.length > 0) {
		this.timeConfig = new TimeConfig(timeConfigNode[0]);
	}
	
	// Animations
	var animationNodes = $('animation', domNode);
	if (animationNodes.length > 0)
	{
		this.animations = [ ];
		var step = this.timeConfig ?
			this.timeConfig.step : variable.timeConfig.step;
		for (var i = 0; i < animationNodes.length; ++i)
		{
			this.animations.push(new AnimationSettings(animationNodes[i], step));
		}
	}

	// Profondeur
	this.hasDepths = false;
	$('level', domNode).each(function(i){
		that.depths[$(this).attr('id')] = $(this).attr('label');
		that.hasDepths = true;
	});

	// Formats
	var formatNodes = $('format', domNode).each(function(i){
		that.formats.push(
				[$(this).attr('id'),
				 $(this).attr('label')]
				);
	});
}
ResultType.prototype = {
/**
 * -----------------------------------------------------------------------------
 * Obtient les paramètres d'animations associés à ce type de résultat.
 */ 
	'getAnimations' : function()
	{
		if (this.animations)
		{
			return this.animations;
		}
		return this.variable.animations;
	},
	'getAnimationsSettings' : function()
	{
		if (this.animations)
		{
			var anims = this.animations;
		}else
		{
			var anims = this.variable.animations;
		}
		if (anims)
		{
			var settings = [ ];
			for (i = 0; i < anims.length; ++i)
			{
				settings.push(anims[i].getSettings());
			}
			return settings;
		}else
		{
			return new Array();
		}
	},
/**
 * -----------------------------------------------------------------------------
 * Obtient la configuration temporelle associée à ce type de résultat.
 */
	'getTimeConfig' : function()
	{
		if (this.timeConfig)
		{
			return this.timeConfig;
		}
		return this.variable.timeConfig;
	}
}
/**
 *  ****************************************************************************
 *  File : design/previmer/javascript/previmer_variable.js
 *  vers : 1.1
 *  build: 20070731
 *  Author : Virtualys
 *  ****************************************************************************
 **/

/**
 * ============================================================================= 
 * Variable
 * Variable Previmer 
 * ============================================================================= 
 */ 
Variable = function(domNode,forTheme)
{
	var resultTypeNodes = null;
	this.id = $(domNode).attr('id');
	this.label = $(domNode).attr('label');
	
	if(!forTheme)
	{
		this.timeConfig = new TimeConfig( $(domNode).children('timeconfig:first-child') );
		this.animations = [];
		var that = this;
		$(domNode).children('animations').children('animation').each(function(i){
			that.animations.push(
					new AnimationSettings(this, that.timeConfig.step));
		})
	}
	this.resultTypes = {
		'map' : null,
		'temporal' : null,
		'section' : null,
		'profile' : null,
		'spectrum' : null };
	var that = this;
	var initResultType = function(i)
	{
		that.resultTypes[$(this).attr('type')] = new ResultType(this, that);
	}
	if (!forTheme)
	{
		$('visualisations > visualisation', domNode).each(initResultType);
	}else
	{
		$('visualisation', domNode).each(initResultType);
	}
}
