/**********************************************************************
 *
 * $Id: wfsLayer.js,v 1.4 2006/04/27 20:02:51 pspencer Exp $
 *
 * purpose: an alternate layer type that can render directly from a
 *          WFS rather than from the tile cache
 *
 * author: Paul Spencer (pspencer@dmsolutions.ca)
 *
 * TODO:
 *   - implementation is very preliminary, missing SRS at least
 *   - layers added don't show up in the legend ...
 * 
 **********************************************************************
 *
 * Copyright (c) 2005, DM Solutions Group Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 *
 **********************************************************************/

/******************************************************************************
 * _wfsLayer - a special type of layer object that represents a WFS layer.  It 
 *             is special because this layer renders directly from the WFS
 *             server rather than through a tile caching service.
 *
 * To use _wfsLayer:
 * 
 * 1) add a script tag to your page:
 * 
 * <script type="text/javascript" src="wfsLayer.js"></script>
 *
 * 2) create a new instance of _wfsLayer
 *
 * var l = new _wfsLayer( szName, bVisible, opacity, imageformat, bQueryable, 
 *                   server, version, layers, srs);
 *
 * 3) add it to the map
 *
 * myKaMap.addMapLayer( l );
 *
 * For instance, assuming you have a form to input the parameters required:
 *
 * function addwfsLayer()
 * {
 *     var f = document.forms.wfs;
 *     var szName = f.wfsName.value;
 *     var bVisible = true;
 *     var opacity = 100;
 *     var imageformat = "image/png";
 *     var bQueryable = true;
 *     var server = f.wfsServer.value;
 *     var version = "1.1.1";
 *     var layers = f.wfsLayers.value;
 *     var srs = f.wfsSRS.value;
 *     var l = new _wfsLayer( szName, bVisible, opacity, imageformat, bQueryable, 
 *                      server, version, layers, srs);
 *     myKaMap.addMapLayer( l );
 * }
 *
 *****************************************************************************/
 
// function _wfsLayer( szName, bVisible, opacity, imageformat, bQueryable, server, version, layers, srs, extent) {
 function _wfsLayer( o ) {
	var map = myKaMap.getCurrentMap();

    this.name = (typeof(o.name) != 'undefined') ? o.name : 'unnamed';
	this.id = (typeof(o.id) != 'undefined') ? o.id : '';
	this.guid = (typeof(o.guid) != 'undefined') ? o.guid : '';
    this.group = (typeof(o.group) != 'undefined') ? o.group : '';
	this.type = (typeof(o.type) != 'undefined') ? o.type : '';
	this.highlight = (typeof(o.highlight) != 'undefined') ? o.highlight : '';
	this.visible = (typeof(o.visible) != 'undefined') ? o.visible : true;
	this.opacity = (typeof(o.opacity) != 'undefined') ? o.opacity : 100;
	this.imageformat = (typeof(o.imageformat) != 'undefined') ? o.imageformat : 'dithered';
    this.imageext = (typeof(o.imageext) != 'undefined') ? o.imageext : '.png';
	this.queryable = (typeof(o.queryable) != 'undefined') ? o.queryable : false;
    this.queryState = (typeof(o.queryable) != 'undefined') ? o.queryable : false;
	this.tileSource = (typeof(o.tileSource) != 'undefined') ? o.tileSource : 'redraw';
	this.extent = (typeof(o.extent) != 'undefined') ? {minx:o.extent.minx,miny:o.extent.miny,maxx:o.extent.maxx,maxy:o.extent.maxy} : {minx:0,miny:0,maxx:0,maxy:0};
//	this.extent = {minx:0,miny:0,maxx:0,maxy:0};
	this.units = (typeof(o.units) != 'undefined') ? o.units : map.units;
	this.scales = (typeof(o.scales) != 'undefined') ? o.scales : new Array();
    this.redrawInterval = (typeof(o.redrawInterval) != 'undefined') ? o.redrawInterval : -1;
    this.refreshInterval = (typeof(o.refreshInterval) != 'undefined') ? o.refreshInterval : -1;

	this.wfs_server = o.wfs_server;
    this.wfs_version = (typeof(o.wfs_version) != 'undefined' && o.wfs_version && o.wfs_version != '') ? o.wfs_version : '1.1.1';
    this.wfs_layer = o.wfs_layer;
    this.wfs_srs = o.wfs_srs;
	this.wfs_style = '&brd='+o.wfs_style.BRD.Type+'-'+o.wfs_style.BRD.Size+'-'+o.wfs_style.BRD.Color
					+ '&bg='+o.wfs_style.BG.Type+'-'+o.wfs_style.BG.Color+'-'+o.wfs_style.BG.BackgroundColor
					+ '&pt='+o.wfs_style.PT.Type+'-'+o.wfs_style.PT.Size+'-'+o.wfs_style.PT.Color+'-'+o.wfs_style.PT.OutlineColor
    this.wfs_maxfeatures = o.wfs_maxfeatures;

    this.viewLegend = (typeof(o.legend) != 'undefined') ? o.legend : 0;
    this.metaWidth = (typeof(o.metaWidth) != 'undefined') ? o.metaWidth : map.kaMap.metaWidth;
    this.metaHeight = (typeof(o.metaHeight) != 'undefined') ? o.metaHeight : map.kaMap.metaHeight;

    this.minScale = (typeof(o.minScale) != 'undefined') ? parseFloat(o.minScale) : 0;
    this.maxScale = (typeof(o.maxScale) != 'undefined') ? parseFloat(o.maxScale) : 0;

	for (i=0;i<map.aScales.length;i++)
		this.scales[i] = 1;

//Debug('this.minScale: '+this.minScale);
//Debug('this.maxScale: '+this.maxScale);

//Debug('this.queryable: '+this.queryable);
//Debug('this.viewLegend: '+this.viewLegend);
//Debug('this.viewLegend: '+this.viewLegend);
//Debug('this.viewLegend: '+this.viewLegend);
//Debug('this.wfs_version: '+this.wfs_version);
//Debug('this.wfs_srs: '+this.wfs_srs);
//Debug('this.wfs_imageformat: '+this.wfs_imageformat);
//Debug('this.wfs_style: '+this.wfs_style);
//Debug('this.wfs_exceptions: '+this.wfs_exceptions);
//	this.zone = map.epsg.substr(3,2);
//Debug('zone: '+this.zone)	;
//Debug(map.units+', '+this.units )
//Debug('Extent-> minx:'+this.extent.minx+', miny:'+this.extent.miny+', maxx:'+this.extent.maxx+', maxy:'+this.extent.maxy);

/*
	if ( map.units != this.units && this.units == 5 ){
		var xy = new Array(2);
		LatLonToUTMXY (DegToRad (this.extent.miny), DegToRad (this.extent.minx), this.zone, xy);
		this.extent.minx = parseInt(xy[0],10);
		this.extent.miny = parseInt(xy[1],10);
		LatLonToUTMXY (DegToRad (this.extent.maxy), DegToRad (this.extent.maxx), this.zone, xy);
		this.extent.maxx = parseInt(xy[0],10);
		this.extent.maxy = parseInt(xy[1],10);
		Debug('New Extent-> minx:'+this.extent.minx+', miny:'+this.extent.miny+', maxx:'+this.extent.maxx+', maxy:'+this.extent.maxy);
	}
*/

	_layer.apply(this,[{ name:this.name
						,id:this.id
						,guid:this.guid
						,group:this.group
						,type:this.type
						,highlight:this.highlight
						,visible:this.visible
						,opacity:this.opacity
						,imageformat:this.imageformat
						,imageext:this.imageext
						,queryable:this.queryable
						,queryState:this.queryState
						,tileSource:this.tileSource
						,extent:this.extent
						,scales:this.scales
						,redrawInterval:this.redrawInterval
						,refreshInterval:this.refreshInterval
					   }]);

	this.bWidthHeight = false; //track adding width/height
    this.baseURL = this.wfs_server;
	/* 
     * make sure the server url is terminated with a ? or not a & so we can
     * append the rest of the request without having to worry about a
     * correctly formatted url
     */
    if (this.baseURL.indexOf('?') == -1) {
        this.baseURL = this.baseURL + '?';
    } else {
        if (this.baseURL.charAt( this.baseURL.length - 1 ) == '&')
            this.baseURL = this.baseURL.slice( 0, -1 );
    }


//	this.baseMapURL = this.baseURL;
    this.baseLegendURL =  map.kaMap.server 
		+ map.kaMap.legendWfsURL
		+ "?wfs="+escape( this.wfs_server )
		+ "&version="+this.wfs_version
		+ "&epsg="+this.wfs_srs.split(':')[1]
		+ "&l="+this.id
		+ "&t="+this.type
		+ "&bbox="+this.extent.minx+','+this.extent.miny+','+this.extent.maxx+','+this.extent.maxy
		+ this.wfs_style
		+ "&w=600&h=600";
//Debug('this.baseLegendURL: '+this.baseLegendURL);

/*
	this.addMapRequestParameter( 'service', "&service=WFS" );
    this.addMapRequestParameter( 'request', "&request=GetMap" );
    this.addMapRequestParameter( 'version', "&version="+this.wfs_version );
    this.addMapRequestParameter( 'layers', "&layers=" + escape(this.wfs_layer) );
    this.addMapRequestParameter( 'srs', "&srs=" + this.wfs_srs );
    this.addMapRequestParameter( 'styles', "&styles=" + this.wfs_style );
    this.addMapRequestParameter( 'format', "&format=" + this.wfs_imageformat );
    this.addMapRequestParameter( 'transparent', '&transparent=TRUE' );
    this.addMapRequestParameter( 'exceptions', '&exceptions=' + this.wfs_exceptions );
*/
    this.addLegendRequestParameter( 'wfs', "&service=WFS" );
    this.addLegendRequestParameter( 'request', "&request=GetLegendGraphic" );
    this.addLegendRequestParameter( 'version', "&version="+this.wfs_version );
    this.addLegendRequestParameter( 'layer', "&layer=" + escape(this.wfs_layer) );
    this.addLegendRequestParameter( 'format', "&format=" + this.wfs_imageformat );

	for (var p in _layer.prototype) {
        if (!_wfsLayer.prototype[p])
            _wfsLayer.prototype[p]= _layer.prototype[p];
    }
};
 
/**
 * wfsLayer.addRequestParameter( name, parameter )
 *
 * add a parameter to the baseURL safely by checking to see if the parameter
 * exists already.  This is an internal function not intended to be used
 * by other code.
 */
 /*
_wfsLayer.prototype.addMapRequestParameter = function( name, parameter ) {
    if (this.baseMapURL.indexOf( name ) == -1) {
        this.baseMapURL = this.baseMapURL + parameter;
    }
};
*/
_wfsLayer.prototype.addLegendRequestParameter = function( name, parameter ) {
    if (this.baseLegendURL.indexOf( name ) == -1) {
        this.baseLegendURL = this.baseLegendURL + parameter;
    }
};



_wfsLayer.prototype.setTile = function(img) {
    var l = safeParseInt(img.style.left) + this._map.kaMap.xOrigin;
    var t = safeParseInt(img.style.top) + this._map.kaMap.yOrigin;

	var bChk = this.CheckTile(l,t);
	
	if ( bChk && !arguments[2] ) return;
	if (arguments[2]){
		img.src = this._map.kaMap.aPixel.src
		return;
	}

	// dynamic imageformat
    var szImageformat = '';
    var image_format = '';
    if (this.imageformat && this.imageformat != '') {
        image_format = this.imageformat;
        szImageformat = '&i='+image_format;
    }
	if(this.tileSource == 'cache' && !img.error && !arguments[1] ) {
	    var metaLeft = Math.floor(l/(this._map.kaMap.tileWidth * this.metaWidth)) * this._map.kaMap.tileWidth * this.metaWidth;
        var metaTop = Math.floor(t/(this._map.kaMap.tileHeight * this.metaHeight)) * this._map.kaMap.tileHeight * this.metaHeight;
        var metaTileId = 't' + metaTop + 'l' + metaLeft;
//		var groupsDir = (this.name != '') ? this.name.replace(/\W/g, '_') : 'def';

//		var cacheDir = this._map.kaMap.webCache + this._map.name + '/' + this._map.aScales[this._map.currentScale] + '/' + groupsDir + '/def/' + metaTileId;
		var cacheDir = this._map.kaMap.webCache 
					 + this.wfs_server.replace(/[\.:?&/]+/g, '') 
					 + '/' + this._map.aScales[this._map.currentScale] 
					 + '/' + this.wfs_layer.replace(/(\W)/g, '_')
//					 + ( this.wfs_style != '' ? '_'+this.wfs_style.replace(/(\W)/g, '_') : '' )
//					 + '_' + this.wfs_srs.split(':')[1]
					 + '_WFS'
					 + '_' + this._map.epsg
					 + '/' + metaTileId;
        var tileId = "t" + t + "l" + l;
        // the following conversion of image format to image extension
        // works for JPEG, GIF, PNG, PNG24 - others may need different treatment
        //var imageExtension = "." + this.imageformat.toLowerCase().replace(/[\de]/g, '') ;
        var imageExtension = this.imageext;
		var src = this._map.kaMap.server + cacheDir + "/" + tileId + imageExtension;
	} else {

		img.error = false;
        var szVersion = '&version='+this.wfs_version;
		var szForce = '';
		if (arguments[1]) { szForce = '&force=true'; }

		var szTimestamp = '';
        if (this.tileSource == 'redraw' || this.tileSource == "refresh") {
            szTimestamp = '&ts='+this.timeStamp;
            if (this.redrawInterval) {
                szTimestamp = szTimestamp + '&interval='+this.redrawInterval;
            }
        }
        
        var szScale = '&s='+this._map.aScales[this._map.currentScale];

		var q = '?';
		if (this._map.kaMap.tileWfsURL.indexOf('?') != -1) {
            if (this._map.kaMap.tileWfsURL.slice(-1) != '&') {
                q = '&';
            } else {
                q = '';
            }
        }

		var src = this._map.kaMap.server
			+ this._map.kaMap.tileWfsURL
			+ q + 'map=' + this._map.name
			+ '&wfs=' + escape(this.wfs_server)
			+ '&version=' + this.wfs_version
			+ '&layers=' + this.wfs_layer
			+ '&type=' + this.type
			+ '&epsg=' + this.wfs_srs.split(':')[1]
			+ '&epsgMap=' + this._map.epsg
			+ '&t=' + t
			+ '&l=' + l
			+ "&mf="+this.wfs_maxfeatures
			+ this.wfs_style
			+ szScale
			+ szForce
			+ szImageformat
			+ szTimestamp;
		if ( this._map.kaMap.metaWidth != this.metaWidth ) src+= '&MW='+this.metaWidth
		if ( this._map.kaMap.metaHeight != this.metaHeight ) src+= '&MH='+this.metaHeight
	}

Debug('_wfsLayer.prototype.setTile: '+img.layer.zIndex+', '+img.id+', <> '+(img.src != src && !(img.ie_hack && img.srcAlpha == src)  || arguments[1] )
	 +', Loaded: '+img.Loaded+'<br>---- img: '+img.src+'<br>---- src: '+src+'<br>---- alpha: '+img.srcAlpha);		
	if (img.src != src  && !(img.ie_hack && img.srcAlpha == src) || arguments[1] ) {
		//this._map.kaMap.nImg++;
        img.style.visibility = 'hidden';
        img.src = src;
    }
}

_wfsLayer.prototype.CheckTile = function( l , t ) {
	var oMap = this._map;
	var oKaMap = this._map.kaMap;

	var ret = false;
//Debug('CheckTile l:'+l+' t:'+t);

	var scale = oKaMap.getCurrentScale()
	var minx = (l * oMap.geoWidth) - oMap.geoBuffer;
	var maxx = minx + oMap.geoWidth * oKaMap.tileWidth;
	var maxy = (-1 * t * oMap.geoHeight) + oMap.geoBuffer;
	var miny = maxy - oMap.geoHeight * oKaMap.tileHeight;

	var Tollerance = oMap.CheckTileTolerance * scale
//Debug('CheckTile Toll: l: '+this.name+', '+Tollerance);
/*
if ( this.extent.minx+this.extent.miny+this.extent.maxx+this.extent.maxy != 0 ) {
		// controllo extent shape o raster
		if (    maxx < this.extent.minx - Tollerance
			 || maxy < this.extent.miny - Tollerance
			 || minx > this.extent.maxx + Tollerance
			 || miny > this.extent.maxy + Tollerance
			)
			ret = true;
	}
*/
//	alert('Livello: '+this.name+' left: '+l+' top: '+t+'\n'+this.extent.minx+','+this.extent.miny+','+this.extent.maxx+','+this.extent.maxy+'\n'+minx+','+miny+','+maxx+','+maxy+'\nReturn: '+ret );
//	return ret;
	// controllo immagini visibili
	var ViewPortExt = oKaMap.getGeoExtents()
	if (    maxx < (ViewPortExt[0])
		 || maxy < (ViewPortExt[1])
		 || minx > (ViewPortExt[2])
		 || miny > (ViewPortExt[3])
		)
		ret = true;
//	alert('Livello: '+this.name+' left: '+l+' top: '+t+'\n'+ViewPortExt[0]+','+ViewPortExt[1]+','+ViewPortExt[2]+','+ViewPortExt[3]+'\n'+minx+','+miny+','+maxx+','+maxy+'\nReturn: '+ret );


	return ret;

//	return ret;

}
/*
 *  addWFSLayer
 *
 */
function addWFSLayer( o ){
	var l = new _wfsLayer( o );
	myKaMap.addWfsLayer( l );
}


