//$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/apps/igeoportal-standard/branches/2.5_testing/modules/mapeditor/mapeditor.js $
/*----------------------------------------------------------------------------
 This file is part of deegree, http://deegree.org/
 Copyright (C) 2001-2009 by:
 - Department of Geography, University of Bonn -
 and
 - lat/lon GmbH -

 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the Free
 Software Foundation; either version 2.1 of the License, or (at your option)
 any later version.
 This library 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 Lesser General Public License for more
 details.
 You should have received a copy of the GNU Lesser General Public License
 along with this library; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 Contact information:

 lat/lon GmbH
 Aennchenstr. 19, 53177 Bonn
 Germany
 http://lat-lon.de/

 Department of Geography, University of Bonn
 Prof. Dr. Klaus Greve
 Postfach 1147, 53001 Bonn
 Germany
 http://www.geographie.uni-bonn.de/deegree/

 e-mail: info@deegree.org
----------------------------------------------------------------------------*/

var baseURL = "http://localhost:8080/geoeditor/ajax";

/**
* MapEditor object realizing toolbar and client server communication
*/
function MapEditor() {
	
	// attributes
	this.doc; 
	this.parentNode;
	this.tb = new Toolbar( "MapEditorTB", new Array(), 250, 35, null );
	this.allowCreation = true;

	// methods
	this.paint = paint;
	this.repaint = repaint;
	this.paintButtons = paintButtons;
	this.setAllowCreation = setAllowCreation;
	this.reset = reset;
	this.actionPerformed = actionPerformed;
	this.loadPreview = loadPreview;
	this.loadObject = loadObject;
	this.loadInputGUI = loadInputGUI;
	this.storeFeature = storeFeature;
	this.setGeometry = setGeometry;
	
	// implementation
	function paint( doc, parentNode) {
		this.doc = doc;
		this.parentNode = parentNode;
		this.paintButtons();
	}
	
	function repaint() {
		var fc = controller.mapModel.getFeatureCollection( "digitizing" );
		var feature = fc.getFeature( 0 );
		if ( feature != null ) {
			var geom = feature.getGeometry();
			if ( geom != null ) {
				setSelectedValue( 'CRS', 'EPSG:31468', this.doc );
				if ( parent.controller.mode == 'mapeditor:drawPoint' ) {
					// write points coordinates to input fields
					setInputValue( 'xCoord', Math.round( geom.x ), this.doc );
					setInputValue( 'yCoord', Math.round( geom.y ), this.doc );
				} else if ( parent.controller.mode == 'mapeditor:drawLineString' ) {
					// TODO
				} else if ( parent.controller.mode == null || 
							parent.controller.mode == 'mapeditor:drawPolygon' ||
						    parent.controller.mode.indexOf( 'Vertex' ) > 5 ) {
					var s = '';
					for ( var i = 0; i < geom.points.length; i++) {
						s += ( Math.round( geom.points[i].x ) + ',' + Math.round( geom.points[i].y ) );
						if ( i < geom.points.length-1 ) {
							s += ',';
						}
					}
					// write polygon coordinates to textarea
					setInputValue( 'TA', s, this.doc );

					// calculate and write centroid to input fields
					var centroid = geom.centroid();
					setInputValue( 'xCenterCoord', Math.round( centroid.x ), this.doc );
					setInputValue( 'yCenterCoord', Math.round( centroid.y ), this.doc );
				} else if ( parent.controller.mode == 'mapeditor:drawBox' ) {
					// write a polygons envelope coordinates to input fields				
					var env = geom.getEnvelope();
					setInputValue( 'minxCoord', Math.round( env.minx ), this.doc );
					setInputValue( 'minyCoord', Math.round( env.miny ), this.doc );
					setInputValue( 'maxxCoord', Math.round( env.maxx ), this.doc );
					setInputValue( 'maxyCoord', Math.round( env.maxy ), this.doc );
				}
			}
		}
	}
	
	function actionPerformed(event) {
		if ( event.source == 'MapEditor' || event.source.getType() == "ToggleButton" ) {
			var mm = parent.controller.mapModel;
			parent.controller.initMapHandling( mm.getWidth(), mm.getHeight(), 0, 0, '#FF0000' );
			parent.controller.mode = event.value;	
			parent.controller.vToolbar.reset();
			if ( event.value == 'mapeditor:drawPoint' ) {
				this.loadInputGUI( 'loadPointGUI' );          
				this.doc.getElementById( 'cbPoint' ).checked = true;
			} else if ( event.value == 'mapeditor:drawLineString' ) {
				// TODO
			} else if ( event.value == 'mapeditor:drawPolygon' ) {
				this.loadInputGUI( 'loadPolygonGUI' );      
				this.doc.getElementById( 'cbPolygon' ).checked = true;
			} 
		} else {
			var fc = controller.mapModel.getFeatureCollection( "digitizing" );
			fc.removeAll();
			controller.repaint();
		}
	}
	
    /**
     * loads a GUI depending on selected geometry type for editing geometry coordinates directly 
     */    
	function loadInputGUI( action, crs ) {			          
        var req = baseURL + '?action=' + action + "&CRS=" + crs;
        submitGetRequest( req, 
            function(result) {
                // inline function definition
                controller.vMapEditor.doc.getElementById( "COORDS" ).innerHTML = result;
            }, 
        null, false );         
    }
	
	
	/**
	* set false if buttons for creating geometries shall not be offered.
	* default is true; 
	*/
	function setAllowCreation(allowCreation) {
		this.allowCreation = allowCreation;
	}
	
	function paintButtons() {
		var bg = new ButtonGroup( "ed1" );
		if ( this.allowCreation ) {
			// these buttons are just avaiable if editor allows creation of 
			// new geometries
			var bt = new ToggleButton( "mapeditor:drawPoint", "draw point", 
			                                 "./images/drawpoint.gif",
			                                 "./images/drawpoint_a.gif" );
			bt.setListener( this );
			bg.addButton( bt );
/*
			bt = new ToggleButton( "mapeditor:drawLine", "draw line", 
			                                 "./images/drawline.gif",
			                                 "./images/drawline_a.gif" );
			bt.setListener( this );
			bg.addButton( );
*/
			bt = new ToggleButton( "mapeditor:drawPolygon", "draw polygon", 
			                                 "./images/drawpolygon.gif",
			                                 "./images/drawpolygon_a.gif" );
			bt.setListener( this );
			bg.addButton( bt );
		}
		var bt = new ToggleButton( "mapeditor:moveVertex", "move vertex", 
		                                 "./images/movevertex.gif",
		                                 "./images/movevertex_a.gif" );
		bt.setListener( this );
        bg.addButton( bt );
        bt = new ToggleButton( "mapeditor:insertVertex", "insert vertex", 
		                                 "./images/insertvertex.gif",
		                                 "./images/insertvertex_a.gif" );
		bt.setListener( this );		                                 
		bg.addButton( bt );
		bt = new ToggleButton( "mapeditor:deleteVertex", "delete vertex", 
		                                 "./images/deletevertex.gif",
		                                 "./images/deletevertex_a.gif" );
		bt.setListener( this );
		bg.addButton( bt );
		bt = new PushButton( "mapeditor:deleteGeom", "delete geometry", 
		                                 "./images/deletegeom.gif",
		                                 "./images/deletegeom_a.gif" );
		bt.setListener( this );
		bg.addButton( bt );
		
		bt = new ToggleButton( "mapeditor:setPolygonCentroid", "set polygon centroid", 
		                                 "./images/polygon_centroid.gif",
		                                 "./images/polygon_centroid_a.gif" );
		bt.setListener( this );
		bg.addButton( bt );
		
        this.tb.addButtonGroup( bg );        
        this.tb.paint( this.doc, this.parentNode );        
	}
	
	/**
	* resets the toolbar assigned to a MapEditor
	*/
	function reset() {
		this.tb.reset();
		parent.controller.mode = '';
	}
	
	/**
	* loads a preview of the passed geometry; If require, first the geometry will be transformed
	* into the maps CRS
	*/
	function loadPreview(geomerty, crs) {
		var gl = new GeometryWrapper( geomerty, crs );
		submitPostRequest( baseURL, loadPreviewHandler, JSON.stringify( gl ), null, true );
	}
	
	/**
	* loads an object with passed ID; If no object with this ID is available the user
	* will be informed of this
	*/
	function loadObject(id) {
		var s = baseURL + "?action=loadObject&objectId=" + id;
        submitGetRequest( s, 
        	function(result) {
				// inline function definition
				var ref = JSON.parse( result );
				if ( ref.geometry == null ) {
					alert( "Eine Georeferenz mit der Kennung: " + ref.objectNo + " ist nicht vorhanden!" );
				}
			}, 
			null, true );         
    }
    
    /**
    * sends a feature to the server to be persited into backend
    */
    function storeFeature(feature, crs, wkt, centroid) {
    	var mm = controller.mapModel;
    	var layerlist = mm.getLayerList();
		var layerGroups = layerlist.getLayerGroups();
		var getMapRequests = new Array();
		var fac = new WMSRequestFactory();
		for(var i = 0; i < layerGroups.length; i++){
	        var src = null;
			if ( controller.vSessionKeeper != null ) {
                src = fac.createGetMapRequest( layerGroups[i], mm, controller.vSessionKeeper.id );
            } else {
                src = fac.createGetMapRequest( layerGroups[i], mm, null );
            }
            getMapRequests.push( src );
		}
    
    	var fl = new FeatureWrapper( feature, crs, wkt, centroid, getMapRequests );
		submitPostRequest( baseURL, storeFeatureHandler, JSON.stringify( fl ), null, true );
    }
    
    function setGeometry(geom) {
    	var props = new Array();
        props[0] = new Object();
        props[0]["Date"] = new Date();
        var feature = new Feature( "ID", null, props, geom );
        var style = getDefaultStyle();
        var mm = parent.controller.mapModel;
        var rendering = new Rendering( featureCollection, style, mm.getWidth(), mm.getHeight(), 0, 0 ); 
        var featureCollection = new FeatureCollection( "FC", new Array() ); 
        controller.mapModel.addFeatureCollection( "digitizing",  featureCollection, rendering );
        featureCollection.addFeature( feature );
        controller.repaint(); 
    }

}

// wrapper and handler objects

function GeometryWrapper (geomerty, crs) {
	this.className = 'createPreview';
	this.geomerty = geomerty;
	this.crs = crs;
}

function FeatureWrapper (feature, crs, wkt, centroid, getMapRequests) {
	this.className = 'store';
	this.feature = feature;
	this.crs = crs;
	this.wkt = wkt;
	this.centroid = centroid;
	this.getMapRequests = getMapRequests;
}

/**
* handler for loading preview result
*/
function loadPreviewHandler(result) {
	var wktada = new WKTAdapter();				
	var geom = wktada.geometryFromText( result );
	
	var event = null;
    if ( result.indexOf( 'POINT' ) > -1  ) {
        event = new Event( 'MapEditor', 'mapeditor:drawPoint' , 'mapeditor:drawPoint' );                
    } else if ( result.indexOf(  'LINESTRING' ) > -1 ) {
        event = new Event( 'MapEditor', 'mapeditor:drawPolygon' , 'mapeditor:drawLineString' );
    } else if ( result.indexOf( 'POLYGON' ) >  -1 ) {                
        event = new Event( 'MapEditor', 'mapeditor:drawPolygon' , 'mapeditor:drawPolygon' );
    }            
    controller.vMapEditor.actionPerformed(event);
          			
    // create feature from geometry returned from server
	var props = new Array();
  	props[0] = new Object();
  	props[0]["Date"] = new Date();
 	var feature = new Feature( "ID", null, props, geom );
 	var mm = controller.mapModel;
    var fc = mm.getFeatureCollection( "digitizing" );
    if ( fc == null ) {
		var style = getDefaultStyle();               
		fc = new FeatureCollection( "FC", new Array() ); 
		var rendering = new Rendering( fc, style, mm.getWidth(), mm.getHeight(), 0, 0 ); 
		controller.mapModel.addFeatureCollection( "digitizing", fc, rendering );
    }
    fc.removeAll();
    fc.addFeature( feature );
             
             // zoom to feature
	if ( result.indexOf( 'POINT' ) > -1  ) {
		bbox = new Envelope( geom.x-50, geom.y-50, geom.x+50, geom.y+50 );
	} else {
		bbox = geom.getEnvelope()
		bbox = bbox.getBuffer( bbox.getWidth()/5 );
    }
    controller.actionPerformed( new Event( this, "BBOX", bbox ) );
}

/**
* handler for storing feature result
*/
function storeFeatureHandler(result) {
	if ( result.indexOf( "EXCEPTION:" ) >= 0 ) {
		alert( result );
	} else {
		alert( "Georeferenz wurde gespeichert!" );
		var bbox = null;
		var wktada = new WKTAdapter();
		var geom = wktada.geometryFromText( result );
        if ( result.indexOf( 'POINT' ) > -1  ) {
			bbox = new Envelope( geom.x-50, geom.y-50, geom.x+50, geom.y+50 );
        } else {
			bbox = geom.getEnvelope()
			bbox = bbox.getBuffer( bbox.getWidth()/5 );
        }
        controller.actionPerformed( new Event( this, "BBOX", bbox ) );
	}				
}
