(function($) {
  var route = new base2.Package(this, {
    name:    "route",
    version: "1.0",
    parent:  dashfly,
    imports: "dashfly",
    exports: "RouteManager"
  });
  
  eval(this.imports);

  var RouteManager = base2.Base.extend({
	  constructor: function(application) {
	  	  this.application = application;
	  	  this.mapManager = application.getService(map.MapManager);
  	  },
 
  	  getDirections: function() {
  		  return directionObj;
  	  },
  	  
  	  getDestination: function() {
  		  return routeDestination;
  	  },
  	  
  	  isRoundTrip: function() {
  		  return (this.getDestination() === null);
  	  },
  	  
  	  getRoute: function(withDestination) {
  		  var addresses = addList.slice();
  		  if (withDestination && this.getDestination()) {
  			  addresses.push(this.getDestination());
  		  }
  		  return addresses;
  	  },
  	  
	  canAddAddress: function(existing) {
		  if (existing == Undefined()) {
			  existing = addList.length;
		  }
		  var maxPoints = getMaximumPoints();
		  if ($('#roundtrip:checked').length === 0) { --maxPoints; }
		  return Math.max(0, maxPoints - existing);
	  },
	  
	  addAddress: function(address) {
		  if (isShowMyRoute) {
			  var index = this.selectPosition(address);
			  Array2.insertAt(addList, index, address);
			  FindRoute();
		  } else {
			  local = [address];
			  addSearchToRoute(0);  
		  }
		  this.ensureRouteIsVisible();
	  },
	  
	  importAddresses: function(stops, replace, block, context) {
		  if (replace) {
			  addList = [];
			  routePointIndex = 0;
			  goBack();
		  }
	  	  	
		  var available = this.canAddAddress();

		  if (available < stops.length) {
			  alert(stops.length + ' addresses were imported.\r\n' +
				   'However, your account only allows ' + available +
	  	  		   '\r\nadditional stop(s) unless you upgrade.\r\n' +
	  	  		   'The additional stops will be ignored.');
		  } else {
			  available = stops.length;
		  }
	  	  	
		  if (available > 0) {
			  var geocodeAndAdd = function(stops) {
			    if (stops.length > 0) {
			    	var stop = stops.shift();
					var address = new DashFlyAddress();
					var line, city, state, zip, label;
					  
					Base.forEach(stop, function(property, name) {
						switch(name.toLowerCase()) {
							case "address": line = property; break;
							case "city": city = property; break;
							case "state": state = property; break;
							case "zipcode": zip = property; break;
							case "label": label = property; break;
						}
					});
					address.SetAddress([line, city, state, zip].join());
					  
					if (label) {
					    address.SetAddressLabel(label + ':' + address.GetAddress());
					} else {
		   				address.SetAddressLabel(address.GetAddress());
					}
					
					this.mapManager.geocode(address, function(address, success) {
						if (success) { this.addAddress(address); }
			   			if ($.isFunction(block)) {
			   				block.call(context, address, success, stops.length === 0);
			   			}
			   			geocodeAndAdd.call(this, stops);
					}, this);
			    }
			  };
			  
			  geocodeAndAdd.call(this, stops.slice(0, available + 1));
		  }
		  else if ($.isFunction(block)) {
			  block.call(context, null, true, true); 
		  }
	  },
	  
      selectPosition: function(address) {
    	  var minDistance, afterIndex = 0;
    	  var latlng = address.GetLatLng();
    	  $('ul#stops tr:first-child').each(function(index) {
    		  var stop = $(this).attr('id');
    		  stop = parseInt(stop.substring(stop.lastIndexOf("_")+1), 10);
    		  var distance = addList[stop].GetLatLng().distanceFrom(latlng);
    		  if (index === 0 || distance <= minDistance) {
    			  minDistance = distance;
    			  afterIndex = index;
    		  }		  
    	  });
    	  
    	  return (afterIndex === 0) ? 1 : afterIndex;
      },
	  
	  ensureRouteIsVisible: function() {
    	  this.mapManager.centerPointsInMap(Array2.map(addList, function(address) {
    		  return address.GetLatLng();
    	  }));
	  }
  });
    
  var RouteModule = Module.extend({
	  load: function() {
	  	 this.routeManager = new RouteManager(this.application);
	  	 this.addService(this.routeManager);
	  	 
	  	 $(delegate(function() {	  		
	  		this.importDialog = $(document.createElement('div'))
	  		  .jqm({toTop: true, modal: false, overlay: 10,
	  			  ajax: this.getUrls().forAction('import'),
	  			  onLoad: delegate(function(hash) {
	  				 this.importDialog.hide().addClass('ui-dialog modalwin').centerInClient();
	  				 $('.tabContainer > ul', this.importDialog).tabs({selected: 0});
	  		 		 $('#import_replace').attr('checked', true);
	  				 this.configureImportFile();
	  				 this.configureImportCSV();
	  				 this.importDialog.show();
	  			  }, this)
	  	 	 });
	  		
			 $('#import_trigger').click(delegate(function() {
				 this.importDialog.jqmShow();
  			 }, this)).show();
			 
	  	     this.importDialog.appendTo(document.body);
	  	 }, this));
  	  },
  	  
	  configureImportFile: function() {
   		  $('#import_file_confirm', this.importDialog).click(delegate(function() {
  			  var replace = $('#import_replace', this.importDialog).get(0);
  			  $('input:file', this.importDialog).each(delegate(function(upload) {	  
				   this.uploadFile(upload, replace.checked,
					  delegate(function(stop, success, done) { 
					   	 if (done) { this.importDialog.jqmHide(); } 
					  }, this));
  			  }, this));
  			  return false;
  		  }, this));  
  	  },
  	  
  	  configureImportCSV: function() {
  		  $('#import_csv_lines', this.importDialog).val(
  			   "Address,City,State,ZipCode,Label\n");
  		  $('#import_csv_confirm', this.importDialog).click(delegate(function() {
  			  var replace = $('#import_replace', this.importDialog).get(0);
  			  this.uploadCSV(replace.checked, delegate(function(stop, success, done) { 
					   	 if (done) { this.importDialog.jqmHide(); } 
					  }, this));
  			  return false;
  		  }, this));  
  	  },
  	  
	  uploadFile: function(selector, replace, block, context) {
	      if ($.trim($(selector).val()).length > 0) {
	    	  $.ajaxFileUpload({dataType: 'json', secureuri: false,
	    		  url: this.application.getUrls().forAjax('importAddresses'),
	    		  fileElementId: $(selector).attr('id'),
	    		  success: delegate(function(t, stops, status) {
	    			  this.routeManager.importAddresses(stops, replace, block, context);
	    		  }, this),
	    	  	  error: function(xhr,status,err) {
	    			  alert('Unable to upload addresses : ' + err);
	    	  	  }
	    	  });
	      }	  
	  },
	  
	  uploadCSV: function(replace, block, context) {
		  $.ajax({type: 'POST', dataType: 'json',
				  url: this.application.getUrls().forAjax('importAddresses'),
			 	  data: {addresses_csv: $('#import_csv_lines', this.importDialog).val()},
				  success: delegate(function(options,stops,status) {
					this.routeManager.importAddresses(stops, replace, block, context);
				  }, this),
				  error: function(xhr,status,err) {
					 alert('Unable to upload addresses : ' + err);
			      }
		  });
	   }	   	 	  
  });
  
  eval(this.exports);
})(jQuery);