// function to submit a sync task 
		// -the url for the feature service and the path to the local geodatabase are passed in
		public async Task SyncronizeEditsAsync(FeatureLayerInfo featureLayerInfo, Uri uri)
		{
			// create sync parameters
			var taskParameters = new SyncGeodatabaseParameters
			{
				RollbackOnFailure = true,
				SyncDirection = SyncDirection.Bidirectional
			};

			// cancel if an earlier call was made and hasn't completed
			if (_syncCancellationTokenSource != null)
			{
				_syncCancellationTokenSource.Cancel();
			}

			// create a new cancellation token
			_syncCancellationTokenSource = new CancellationTokenSource();
			var cancelToken = _syncCancellationTokenSource.Token;


			// create a sync task with the url of the feature service to sync
			var syncTask = new GeodatabaseSyncTask(uri);

			// create a new Progress object to report updates to the sync status
			var progress = new Progress<GeodatabaseStatusInfo>();
			progress.ProgressChanged += (sender, s) => { _model.SetMessageInfo("Progress: " + s.Status.ToString()); };

			// call SyncGeodatabaseAsync and pass in: sync params, local geodatabase, completion callback, update interval, progress, and cancellation token

			var geodatabaseFeatureTable = featureLayerInfo.FeatureLayer.FeatureTable as GeodatabaseFeatureTable;

			var gdbResult = await syncTask.SyncGeodatabaseAsync(
				taskParameters,
				geodatabaseFeatureTable.Geodatabase,
				(p, q) =>
				{
					// reset the cancellation token source
					_syncCancellationTokenSource = null;

					// if unsuccessful, report the exception and return
					if (q != null)
					{
						_model.SetMessageInfo("An exception occured: " + q.Message);
						return;
					}

					// if successful, notify the user
					_model.SetMessageInfo("--- Sync completed ---");

					//// optionally, do something with the result
					//var resultUri = p.ResultUri;
					// ...

					UpdateToc(featureLayerInfo);
					_model.SetSyncState(CheckSyncState(false));
				},
				null,
				new TimeSpan(0, 0, 10),
				progress,
				cancelToken);
		}
		private async Task<Uri> GetFeatureServiceUrlForSync(FeatureLayerInfo featureLayerInfo)
		{
			var arcGisPortal = await ArcGISPortal.CreateAsync(_model.DefaultServerUri);
			var item = await ArcGISPortalItem.CreateAsync(arcGisPortal, _currentOfflineMapItem.WebMapId);
			var webMap = await WebMap.FromPortalItemAsync(item);
			foreach (var webMapItem in webMap.OperationalLayers)
			{
				if (webMapItem.Title.Contains(featureLayerInfo.FeatureLayer.ID))
				{
					var uri = new Uri(webMapItem.Url);
					var newSegments = uri.Segments.Take(uri.Segments.Length - 1).ToArray();
					newSegments[newSegments.Length - 1] = newSegments[newSegments.Length - 1].TrimEnd('/');
					var uriBuilder = new UriBuilder(uri) {Path = string.Concat(newSegments)};

					return uriBuilder.Uri;
				}
			}
			return null;
		}
		private async Task CreateToc()
		{
			FeatureLayerInfoItems.Clear();
			if (CurrentEsriMapView == null) return;

			foreach (var layer in CurrentEsriMapView.Map.Layers)
			{
				if (!(layer is FeatureLayer)) continue;

				var featureLayer = layer as FeatureLayer;
				long edits = 0;
				FeatureServiceLayerInfo serviceInfo = null;
				if (featureLayer.FeatureTable is GeodatabaseFeatureTable)
				{
					var table = featureLayer.FeatureTable as GeodatabaseFeatureTable;
					if (table.HasEdits)
					{
						edits = table.AddedFeaturesCount + table.DeletedFeaturesCount + table.UpdatedFeaturesCount;
					}

					serviceInfo = table.ServiceInfo;
				}

				if (featureLayer.FeatureTable is ServiceFeatureTable) //online
				{
					var table = featureLayer.FeatureTable as ServiceFeatureTable;
					if (table.HasEdits)
					{
						edits = table.AddedFeaturesCount + table.DeletedFeaturesCount + table.UpdatedFeaturesCount;
					}

					serviceInfo = table.ServiceInfo;
				}


				bool isEditable = false;
				bool isSyncable = false;
				foreach (var capability in serviceInfo.Capabilities)
				{
					if (capability == "Editing")
					{
						isEditable = true;
					}
					if (capability == "Sync")
					{
						isSyncable = true;
					}
				}

				if (isEditable)
				{
					// var test = featureLayer.FeatureTable.ServiceInfo.DrawingInfo.Renderer as SimpleRenderer;
					// UniqueValueInfoCollection uniqueValueInfoCollection = test.;

					var legendInfosList = new List<LegendInfo>();

					if (serviceInfo.DrawingInfo.Renderer is SimpleRenderer)
					{
						var renderer =
							serviceInfo.DrawingInfo.Renderer as SimpleRenderer;
						var imageSource = await renderer.Symbol.CreateSwatchAsync();
						var legendInfo = new LegendInfo(renderer.Label, imageSource, renderer.Symbol, CreateNewFeatureCommand);
						legendInfosList.Add(legendInfo);
					}
					else if (serviceInfo.DrawingInfo.Renderer is UniqueValueRenderer)
					{
						var renderer = serviceInfo.DrawingInfo.Renderer as UniqueValueRenderer;
						foreach (var info in renderer.Infos)
						{
							var imageSource = await info.Symbol.CreateSwatchAsync();
							legendInfosList.Add(new LegendInfo(info.Label, imageSource, info.Symbol, CreateNewFeatureCommand));
						}
					}
					else if (serviceInfo.DrawingInfo.Renderer is ClassBreaksRenderer)
					{
						var renderer = serviceInfo.DrawingInfo.Renderer as ClassBreaksRenderer;

						foreach (var info in renderer.Infos)
						{
							var imageSource = await info.Symbol.CreateSwatchAsync();
							legendInfosList.Add(new LegendInfo(info.Label, imageSource, info.Symbol, CreateNewFeatureCommand));
						}
					}

					var featureLayerEditInfoItem = new FeatureLayerInfo(featureLayer, isEditable, isSyncable, edits, legendInfosList);
					FeatureLayerInfoItems.Add(featureLayerEditInfoItem);
				}
			}
		}
		private void UpdateToc(FeatureLayerInfo featureLayerInfo)
		{
			if (CurrentEsriMapView == null) return;

			long edits = 0;
			if (featureLayerInfo.FeatureLayer.FeatureTable is GeodatabaseFeatureTable)
			{
				var table = featureLayerInfo.FeatureLayer.FeatureTable as GeodatabaseFeatureTable;
				if (table.HasEdits)
				{
					edits = table.AddedFeaturesCount + table.DeletedFeaturesCount + table.UpdatedFeaturesCount;
				}
			}

			if (featureLayerInfo.FeatureLayer.FeatureTable is ServiceFeatureTable) //online
			{
				var table = featureLayerInfo.FeatureLayer.FeatureTable as ServiceFeatureTable;
				if (table.HasEdits)
				{
					edits = table.AddedFeaturesCount + table.DeletedFeaturesCount + table.UpdatedFeaturesCount;
				}
			}
			featureLayerInfo.Edits = edits;
		}
		private async Task CreateNewFeature(FeatureLayerInfo featureLayerInfo, LegendInfo legendInfo)
		{
			if (CurrentEsriMapView.Editor.IsActive)
			{
				CurrentEsriMapView.Editor.Cancel.Execute(null);
			}
			Graphic graphic = null;

			switch (featureLayerInfo.FeatureLayer.FeatureTable.GeometryType)
			{
				case GeometryType.Unknown:
					break;
				case GeometryType.Point:
					graphic = await CreateGraphicAsync(legendInfo.EsriSymbol, DrawShape.Point);
					break;
				case GeometryType.Polyline:
					graphic = await CreateGraphicAsync(legendInfo.EsriSymbol, DrawShape.Polyline);
					break;
				case GeometryType.Polygon:
					graphic = await CreateGraphicAsync(legendInfo.EsriSymbol, DrawShape.Polygon);
					break;
				case GeometryType.Envelope:
					break;
			}


			if (featureLayerInfo.FeatureLayer.FeatureTable is GeodatabaseFeatureTable)
			{
				var table = featureLayerInfo.FeatureLayer.FeatureTable as GeodatabaseFeatureTable;
				//_model.SetMessageInfo("Table was not found in the local geodatabase.");
				var feature = new GeodatabaseFeature(table.Schema) {Geometry = graphic.Geometry,};

				if (feature.Schema.Fields.Any(fld => fld.Name == table.ServiceInfo.DisplayField))
					feature.Attributes[table.ServiceInfo.DisplayField] = legendInfo.Label;

				await table.AddAsync(feature);
			}

			if (featureLayerInfo.FeatureLayer.FeatureTable is ServiceFeatureTable)
			{
				var table = featureLayerInfo.FeatureLayer.FeatureTable as ServiceFeatureTable;

				var feature = new GeodatabaseFeature(table.Schema) {Geometry = graphic.Geometry,};

				if (feature.Schema.Fields.Any(fld => fld.Name == table.ServiceInfo.DisplayField))
					feature.Attributes[table.ServiceInfo.DisplayField] = legendInfo.Label;

				await table.AddAsync(feature);
			}
		}