
function OptimRoute(settings)
{
	this.addStartPoint = addStartPoint;
	this.addEndPoint   = addEndPoint;
	this.addViaPoint   = addViaPoint;	
	this.getExtent	   = getExtent;	
	this.run		       = run;
	this.setMap	   	   = setMap;

	this.createSortable      = createSortable;
	this.getPathDescription  = getPathDescription;
	this.zoomTo              = zoomTo;
	
	
	var scriptPath		     = settings['clientScriptPath'];
	var	serverOptimUrl     = settings['serverOptimUrl'];	
	var popupScriptPath    = settings['popupScriptPath'];
	
	var routeMap		       = null;
	var layerOptimResult   = null;
	var layerOptimMarkers	 = null;
	var layerOptimSegments = null;
	var popup              = null;
  var optimPoints        = new  optimPoints();
  
  createSortable();
  
  
  function setMap(map)
	{
    routeMap = map
    layerOptimMarkers = new OpenLayers.Layer.Markers("optimmarkers");
    layerOptimSegments = new OpenLayers.Layer.Markers("optim_segments");
    layerOptimMarkers.displayInLayerSwitcher = true;
    layerOptimSegments.displayInLayerSwitcher = true;
    map.addLayers([layerOptimSegments,layerOptimMarkers]);    
		
	}
	
	function optimPoint()
	{
      
      this.setGeom      = setGeom;
      this.setOrder     = setOrder;
      this.setLocation  = setLocation;
      this.setType      = setType;
      this.setMarker    = setMarker;
      this.setSortable  = setSortable;
      this.removeSortable  = removeSortable;
      
      this.getGeom      = getGeom;
      this.getOrder     = getOrder;
      this.getLocation  = getLocation;
      this.getType      = getType;
      this.removeMarker = removeMarker;
      
      var geom;
      var marker; 
      var order;
      var location;
      var marker;
      var type;
      
      this.START_ROUTE      = 1;
	    this.VIA_ROUTE        = 2;
      this.STOP_ROUTE       = 3;
      
      function setGeom(ge)
      {
          geom = ge;
      }
      
      function getGeom()
      {
          return geom;
      }
      
      function setType(ty)
      {
          type = ty;
      }
      
      function getType()
      {
        return type;
      }
      
      function setMarker(markerlayer)
    	{
    		if (marker == null)
    		{
            var point_merc  = OpenLayers.Projection.transform( getGeom(), "epsg:4326", "epsg:54004");
        		var size        = new OpenLayers.Size(20,20);
        	 	var offset      = new OpenLayers.Pixel(-(size.w/2), -size.h);
        	 	
        	 	if (this.START_ROUTE ==  getType())
        	 	  var icon  = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'start_route.png',size,offset);	
        	  else if (this.VIA_ROUTE ==  getType())        
              var icon  = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'via_route.png',size,offset);
            else if (this.STOP_ROUTE ==  getType() )
              var icon  = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'stop_route.png',size,offset);
            
            marker      = new OpenLayers.Marker(new OpenLayers.LonLat(point_merc.x,point_merc.y),icon);
        		markerlayer.addMarker(marker);	
    		}
    	}
      
      function setSortable(order)
	    {
	        if (document.getElementById('sortableoptim_'+order) == null)
	        { 
              
              var closeB = '<img style="cursor:pointer;margin-right:4px" id=sortable_optim_close'+order+' src='+OpenLayers.Util.getImagesLocation() + 'close.gif'+'>';
              
              $jq('#srchPointOrder')
                  .append('<div id="sortableoptim_'+order+'" class="optimloc">'+closeB+getLocation()+'</div>')
                  .SortableAddItem(document.getElementById('sortableoptim_'+order));
              
              if (this.START_ROUTE ==  getType())
                  $jq('#sortableoptim_'+order).css('background-color','lime');
              else if (this.VIA_ROUTE ==  getType()) 
                  $jq('#sortableoptim_'+order).css('background-color','yellow');
              else if (this.STOP_ROUTE ==  getType() )
                  $jq('#sortableoptim_'+order).css('background-color','red');
                  
              $jq('#sortable_optim_close'+order).click(function()
              {
                  removeSortable(order);
                  removeMarker(layerOptimMarkers);
                  optimPoints.removePoint(getGeom());
              
              });
          
          }     
            
      }
      
      function removeSortable(order)
	    {
          var d = document.getElementById('srchPointOrder');
          var olddiv = document.getElementById('sortableoptim_'+order);
          if (olddiv != null) d.removeChild(olddiv);
      }
      
      function removeMarker(markerlayer)
      {
          if (marker != null)
          {
              markerlayer.removeMarker(marker);
              marker = null;
          }    
      }
      
      function setLocation(lo)
      {
          location = lo;
      }
      
      function getLocation()
      {
          return location;
      }
      
      function setOrder(or)
      {
          order = or;
      }
      
      function getOrder()
      {
          return order;
      }
      
      
  }
	
	function optimPoints()
	{
	    var points     = [];
      var optimstring; 
      this.addPoint  = addPoint;
      this.removePoint = removePoint;
      this.replaceStartEndPoint = replaceStartEndPoint;
      this.pointExists          =  pointExists;  
      this.sortPointsByOrder    =  sortPointsByOrder;  
      this.sortPointsByType     =  sortPointsByType;
      this.compareOrders        =  compareOrders;
      this.createOptimString    =  createOptimString;
      this.compareTypes         =  compareTypes;
      this.orderPointBySorter   =  orderPointBySorter;
      this.setOrder             =  setOrder;
      this.getOptimString       =  getOptimString;
      
      function addPoint(p)
      {
          if (pointExists(p)){return;} 
          if (!replaceStartEndPoint(p)){points.push(p); }
          setOrder();
          sortPointsByOrder();
      }
      
      function setOrder()
      {
          var countVia = 1;
          for (var z = 0; points.length>z ;z++)
          {
               if ((points[z].getType()) == (p.START_ROUTE)) {points[z].setOrder(1)}
               if ((points[z].getType()) == (p.VIA_ROUTE))   {countVia++ ; points[z].setOrder(countVia);}  
               if ((points[z].getType()) == (p.STOP_ROUTE))  {points[z].setOrder(points.length);}
          }
      }
      
      function orderPointBySorter(neworder)
      {
           for (var z = 0; points.length>z ;z++)
           {
              thisorder = neworder[ points[z].getOrder() ];
              points[z].setOrder(thisorder);
              
              if   (thisorder==1)
              { 
                  points[z].setType(points[z].START_ROUTE);
              }    
              else if (thisorder == (points.length)) 
              {
                  points[z].setType(points[z].STOP_ROUTE);
              }
              else
              {
                  points[z].setType(points[z].VIA_ROUTE);
              }  
           }
      }
      
      function removePoint(geometry)
      {
           for (var f = 0; points.length>f ;f++)
           {
              points[f].removeSortable(points[f].getOrder() ); 
           }
           for (var z = 0; points.length>z ;z++)
           {
              if (points[z].getGeom().x == geometry.x && points[z].getGeom().y == geometry.y)
              {
                  if (layerOptimResult != null){layerOptimResult.destroy()}
                  points.splice(z, 1);
                  if (points.length > 0)
                  {
                    points[0].setType(points[0].START_ROUTE);
                    points[points.length-1].setType(points[points.length-1].STOP_ROUTE);
                  }
                  setOrder();
                  sortPointsByOrder();
                  break;
              }
           }
           
      }
      
      function replaceStartEndPoint(p)
      {
           for (var z = 0; points.length>z ;z++)
           {
               if ( p.getType() == p.START_ROUTE || p.getType() == p.STOP_ROUTE )
               {
                    if( points[z].getType() == p.getType() )
                    {
                      points[z].removeSortable(points[z].getOrder() ); 
                      points[z].removeMarker(layerOptimMarkers);
                      points.splice(z, 1, p);
                      return true;
                    }
               }
           }
           return false;
      }
      
      function pointExists(p)
      {
           for (var z = 0; points.length>z ;z++)
           {
              if (points[z].getGeom().x == p.getGeom().x && points[z].getGeom().y == p.getGeom().y)
              {
                  return true;
              } 
           }
           return false; 
      }
     
     function compareOrders(a , b)
     {
        return a.getOrder() - b.getOrder();
     }
     
     function compareTypes(a , b)
     {
        return a.getType() - b.getType();
     }
     
     function sortPointsByOrder()
     {
        points.sort(compareOrders);
        createOptimString();
     }
     
     function sortPointsByType()
     {
        points.sort(compareTypes);
     }
     
     function getOptimString()
     {
        return optimstring;
     }
     
     function createOptimString()
     {
         hasStart    = false;
         hasStop     = false; 
         optimstring = '';

         for (var z = 0; points.length>z ;z++)
         {
              if (points[z].getType() ==  points[z].START_ROUTE) hasStart = true;
              if (points[z].getType() ==  points[z].STOP_ROUTE)  hasStop  = true;
              points[z].removeSortable(points[z].getOrder() ); 
              points[z].removeMarker(layerOptimMarkers);
              points[z].setSortable(points[z].getOrder() ); 
              points[z].setMarker(layerOptimMarkers);
              optimstring+=points[z].getGeom().x+"x"+points[z].getGeom().y+",";
         }
         if (hasStart && hasStop) 
         {
            optimstring = optimstring.substring(0,optimstring.length-1);
            run();
         }
     }
      
  }
	
	function createSortable()
	{
  	$jq('#srchPointOrder').Sortable(
  	{
  		accept      : 'optimloc',
  		activeclass : 'sortableactive',
  		hoverclass  : 'sortablehover',
  		helperclass : 'sorthelper',
  		opacity     : 	0.5,
  		fit         :	false,
  		onStop : function()
      {
         serial = $jq.SortSerialize('srchPointOrder');
         s1 = serial.hash.split( "&" );
         var neworder = [];
         var c = 0;
         for (var z = 0; s1.length>z ;z++)
         {
             c++; 
             s2 = s1[z].split("=");
             for (var v = 0; s2.length/2>v ;v++)
             {
                xpc = s2[1].split("_");
                order = xpc[1];  
                neworder[order]=c;
                
             }
         }
         optimPoints.orderPointBySorter(neworder);
         optimPoints.sortPointsByOrder();
      }
  	});
	}
  
	function addStartPoint(sPoint,description)
	{
	   p = new optimPoint();
	   p.setType(p.START_ROUTE);
	   p.setGeom(sPoint);
	   p.setLocation(description);
	   optimPoints.addPoint(p);
	   getExtent();
	}
	
	function addEndPoint(ePoint,description)
	{
     p = new optimPoint();
	   p.setType(p.STOP_ROUTE);
	   p.setGeom(ePoint);
	   p.setLocation(description);
	   optimPoints.addPoint(p);
	   getExtent();
	}
	
	function addViaPoint(vPoint,description)
	{
     p = new optimPoint();
	   p.setType(p.VIA_ROUTE);
	   p.setGeom(vPoint);
	   p.setLocation(description);
	   optimPoints.addPoint(p);
	   getExtent();
	}
	
	function getExtent()
	{	
		routeMap.zoomToExtent (layerOptimMarkers.getDataExtent());	
	}
	
	function zoomTo(x1,y1,x2,y2,streetName,segLen,totalSegLen)
	{
    
    var point1       = new OpenLayers.Geometry.Point(x1, y1);
    var point2       = new OpenLayers.Geometry.Point(x2, y2);
    var point_merc1  = OpenLayers.Projection.transform(point1, "epsg:4326", "epsg:54004");
    var point_merc2  = OpenLayers.Projection.transform(point2, "epsg:4326", "epsg:54004");

    layerOptimSegments.clearMarkers();
    
    $jq.get(popupScriptPath,{SEGNAME:streetName,LEN:segLen,TOTALLEN:totalSegLen,x:point1.x,y:point1.y},function(data) 
  	{
          
          var size = new OpenLayers.Size(20,30);
          var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
          var iconStart = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'bar_white_start.png',size,offset);	
          var markerStart = new OpenLayers.Marker(new OpenLayers.LonLat(point_merc1.x,point_merc1.y),iconStart)
          var iconEnd = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'bar_white_start.png',size,offset);	
          var markerEnd = new OpenLayers.Marker(new OpenLayers.LonLat(point_merc2.x,point_merc2.y),iconEnd)
          
          layerOptimSegments.addMarker(markerStart);
          layerOptimSegments.addMarker(markerEnd);
          
          var xc = (point_merc1.x + point_merc2.x) /2
          var yc = (point_merc1.y + point_merc2.y) /2
    						
          if (popup != null)
					{
              popup.destroy();
          }
          popup = new OpenLayers.Popup.Anchored("fghuziu", 
                                   new OpenLayers.LonLat(point_merc1.x,point_merc1.y),
                                   new OpenLayers.Size(400,400),
                                   data,null,true);
                                 
          routeMap.addPopup(popup);
          
          //display minimap
          var iconStartClone = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'bar_white_start.png',size,offset);	
          var markerStartClone = new OpenLayers.Marker(new OpenLayers.LonLat(point_merc1.x,point_merc1.y),iconStartClone)
          var iconEndClone = new OpenLayers.Icon(OpenLayers.Util.getImagesLocation() + 'bar_white_start.png',size,offset);	
          var markerEndClone = new OpenLayers.Marker(new OpenLayers.LonLat(point_merc2.x,point_merc2.y),iconEndClone)
          
          layerOptimSegmentsClone = new OpenLayers.Layer.Markers("optim_segments_clone");
          layerOptimSegmentsClone.addMarker(markerStartClone);
          layerOptimSegmentsClone.addMarker(markerEndClone);
          
          mapSettings['div'] = 'scrsht'
          var cloneRouteMap = new OLMap(mapSettings);
          cloneRouteMapObj = cloneRouteMap.getMap();
          var ctls = cloneRouteMapObj.controls;
          for (var z = 1; ctls.length>z ;z++) 
          {
            $jq(ctls[z].div).hide();
          }
          cloneRouteMapObj.addLayers([layerOptimResult.clone(),layerOptimSegmentsClone]);
          cloneRouteMapObj.zoomToExtent (layerOptimSegments.getDataExtent());
  	});
     
    
  	//routeMap.zoomToExtent (layerOptimSegments.getDataExtent());
  }
	
	function getPathDescription(optkey)
	{
        $jq.get(scriptPath ,{method:'3',optimkey:optkey},function(xml)
				{
            $jq(routePathDescr).html(xml);
        });        
        return true;     							
  }
	
	function run()
	{
      var optimstring = optimPoints.getOptimString();
      if ( optimstring.length == 0) return false;
      if (layerOptimResult != null){layerOptimResult.destroy()}
    
      $jq(userMsgPanel).show();
			$jq(userMsg).html('... optim in progress ...');
			$jq('.result_line2').hide();
			
			for (var i=0; i < document.optimSettings.path_cost.length; i++)
      {
          if (document.optimSettings.path_cost[i].checked)
          {
             var optim_kind = document.optimSettings.path_cost[i].value;
          }
      }
			
			$jq.get
			(
						scriptPath,{method:'1', kind: optim_kind, oPoints:optimstring }, function(data) 
						{
								if (routeMap != null)
								{
                        if (data.substr(0,5) != "false") // ni bilo uspesne optimizacije
									      {
                            //create optim result layer with sld body test
                            layerOptimResult = new OpenLayers.Layer.WMS
                            (
                                "Route",
                                serverOptimUrl,
                                {layers: 'streets_group' ,format: "image/png8" , transparent:true},{ isBaseLayer: false , singleTile: true } 
                            );
          									layerOptimResult.ratio=1;
          									layerOptimResult.mergeNewParams({"SLD":scriptPath+"?method=2&optimkey="+data})
          									layerOptimResult.displayInLayerSwitcher = true;
          									routeMap.addLayer(layerOptimResult);
                            layerOptimResult.setZIndex(200);
          									getPathDescription(data);
      									}
      									else
      									{
                             alert(getMessage('msgoptim1'));
                        }
                        $jq(userMsg).html('');
          							$jq(userMsgPanel).hide();
          							$jq('.result_line2').show();  
								}
           }
      );
                
	}


}

