public bool GetDestEntriesToDelete(CalendarSyncProfile syncProfile, CalendarAppointments sourceList,
     CalendarAppointments destinationList)
 {
     EvaluateAppointmentsToDelete(syncProfile, sourceList, destinationList, DestAppointmentsToDelete,
         DestAppointmentsToUpdate, SourceAppointmentsToUpdate, DestOrphanEntries);
     return true;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="syncProfile"></param>
        /// <param name="syncMetric"></param>
        /// <param name="sourceCalendarSpecificData"></param>
        /// <param name="destinationCalendarSpecificData"></param>
        /// <returns></returns>
        private bool UpdateEntries(CalendarSyncProfile syncProfile, SyncMetric syncMetric,
            IDictionary<string, object> sourceCalendarSpecificData,
            IDictionary<string, object> destinationCalendarSpecificData)
        {
            var isSuccess = true;
            if (CalendarSyncEngine.SourceAppointmentsToUpdate.Any())
            {
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                //Update status for reading entries to update
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.EntriesToUpdate,
                    CalendarSyncEngine.SourceAppointmentsToUpdate.Count,
                    SourceCalendarService.CalendarServiceName);
                var updatedAppointments = SourceCalendarService.UpdateCalendarEvents(CalendarSyncEngine.SourceAppointmentsToUpdate,
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Description),
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Reminders),
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Attendees),
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.AttendeesToDescription),
                    sourceCalendarSpecificData).Result;
                isSuccess = updatedAppointments.IsSuccess;
                SyncStatus =
                    StatusHelper.GetMessage(isSuccess
                        ? SyncStateEnum.UpdateEntriesSuccess
                        : SyncStateEnum.UpdateEntriesFailed);
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                syncMetric.SourceMetric.UpdateCount = CalendarSyncEngine.SourceAppointmentsToUpdate.Count;
                syncMetric.SourceMetric.UpdateFailedCount =
                    CalendarSyncEngine.SourceAppointmentsToUpdate.Count - updatedAppointments.Count;
            }

            if (CalendarSyncEngine.DestAppointmentsToUpdate.Any())
            {
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                //Update status for reading entries to update
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.EntriesToUpdate,
                    CalendarSyncEngine.DestAppointmentsToUpdate.Count,
                    DestinationCalendarService.CalendarServiceName);
                var updatedAppointments = DestinationCalendarService.UpdateCalendarEvents(CalendarSyncEngine.DestAppointmentsToUpdate,
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Description),
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Reminders),
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Attendees),
                    syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.AttendeesToDescription),
                    destinationCalendarSpecificData).Result;
                isSuccess = updatedAppointments.IsSuccess;
                SyncStatus =
                    StatusHelper.GetMessage(isSuccess
                        ? SyncStateEnum.UpdateEntriesSuccess
                        : SyncStateEnum.UpdateEntriesFailed);
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                syncMetric.DestMetric.UpdateCount = CalendarSyncEngine.DestAppointmentsToUpdate.Count;
                syncMetric.DestMetric.UpdateFailedCount =
                    CalendarSyncEngine.DestAppointmentsToUpdate.Count - updatedAppointments.Count;
            }

            return isSuccess;
        }
 private void InitiatePreSyncSetup(CalendarSyncProfile syncProfile)
 {
     SourceCalendarService = CalendarServiceFactory.GetCalendarService(syncProfile.SyncSettings.SourceCalendar);
     DestinationCalendarService =
         CalendarServiceFactory.GetCalendarService(syncProfile.SyncSettings.DestinationCalendar);
 }
 private void GetDateRange(CalendarSyncProfile syncProfile, out DateTime startDate, out DateTime endDate)
 {
     startDate = syncProfile.SyncSettings.StartDate.Date;
     endDate = syncProfile.SyncSettings.EndDate.Date;
     if (syncProfile.SyncSettings.SyncRangeType == SyncRangeTypeEnum.SyncRangeInDays)
     {
         startDate = DateTime.Today.AddDays((-syncProfile.SyncSettings.DaysInPast));
         endDate = DateTime.Today.AddDays((syncProfile.SyncSettings.DaysInFuture + 1));
     }
     else if (syncProfile.SyncSettings.SyncRangeType == SyncRangeTypeEnum.SyncEntireCalendar)
     {
         startDate = DateTime.Parse("1990/01/01 12:00:00 AM");
         endDate = DateTime.Today.AddYears(10);
     }
 }
 private IDictionary<string, object> GetCalendarSpecificData(CalendarServiceType serviceType,
     CalendarSyncProfile syncProfile)
 {
     IDictionary<string, object> calendarSpecificData = null;
     switch (serviceType)
     {
         case CalendarServiceType.Google:
             calendarSpecificData = new Dictionary<string, object>
             {
                 {"CalendarId", syncProfile.GoogleAccount.GoogleCalendar.Id},
                 {"AccountName", syncProfile.GoogleAccount.Name}
             };
             break;
         case CalendarServiceType.OutlookDesktop:
             calendarSpecificData = new Dictionary<string, object>
             {
                 {
                     "ProfileName",
                     !syncProfile.OutlookSettings.OutlookOptions.HasFlag(OutlookOptionsEnum.DefaultProfile)
                         ? syncProfile.OutlookSettings.OutlookProfileName
                         : null
                 },
                 {
                     "OutlookCalendar",
                     !syncProfile.OutlookSettings.OutlookOptions.HasFlag(OutlookOptionsEnum.DefaultCalendar)
                         ? syncProfile.OutlookSettings.OutlookCalendar
                         : null
                 },
                 {
                     "AddAsAppointments",
                     syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.AsAppointments)
                 }
             };
             break;
         case CalendarServiceType.EWS:
             return null;
     }
     if (calendarSpecificData != null && syncProfile.SetCalendarCategory)
     {
         calendarSpecificData.Add("EventCategory", syncProfile.EventCategory);
     }
     return calendarSpecificData;
 }
 private string GetCalendarName(CalendarSyncProfile syncProfile, CalendarServiceType calendarServiceType)
 {
     switch (calendarServiceType)
     {
         case CalendarServiceType.Google:
             return string.Format("{0} - {1}", syncProfile.GoogleAccount.Name,
                 syncProfile.GoogleAccount.GoogleCalendar.Name);
         case CalendarServiceType.OutlookDesktop:
             return syncProfile.OutlookSettings.OutlookOptions.HasFlag(OutlookOptionsEnum.DefaultCalendar)
                 ? "Default Calendar"
                 : string.Format("{0} - {1}", syncProfile.OutlookSettings.OutlookMailBox.Name,
                     syncProfile.OutlookSettings.OutlookCalendar.Name);
     }
     return string.Empty;
 }
        /// <summary>
        ///     Delete appointments from source
        /// </summary>
        /// <param name="syncProfile"></param>
        /// <param name="sourceCalendarSpecificData"></param>
        /// <param name="syncCallback"></param>
        /// <returns>
        /// </returns>
        private bool DeleteSourceAppointments(CalendarSyncProfile syncProfile, SyncMetric syncMetric,
            IDictionary<string, object> sourceCalendarSpecificData, SyncCallback syncCallback)
        {
            if (syncProfile.SyncSettings.DisableDelete)
            {
                return true;
            }
            //Updating entry isDeleteOperation status
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.ReadingEntriesToDelete,
                SourceCalendarService.CalendarServiceName);
            //Getting appointments to isDeleteOperation
            CalendarSyncEngine.GetSourceEntriesToDelete(syncProfile, SourceAppointments, DestinationAppointments);
            var appointmentsToDelete = CalendarSyncEngine.SourceAppointmentsToDelete;
            //Updating Get entry isDeleteOperation status
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.EntriesToDelete, appointmentsToDelete.Count);
            if (appointmentsToDelete.Count == 0)
            {
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                return true;
            }

            //Updating isDeleteOperation status
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.DeletingEntries,
                SourceCalendarService.CalendarServiceName);
            //Deleting entries
            var deletedAppointments =
                SourceCalendarService.DeleteCalendarEvents(appointmentsToDelete, sourceCalendarSpecificData).Result;
            var isSuccess = deletedAppointments.IsSuccess;
            //Update status if entries were successfully deleted
            SyncStatus =
                StatusHelper.GetMessage(isSuccess
                    ? SyncStateEnum.DeletingEntriesComplete
                    : SyncStateEnum.DeletingEntriesFailed);
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);

            if (isSuccess)
            {
                syncMetric.SourceMetric.DeleteCount = appointmentsToDelete.Count;
                syncMetric.SourceMetric.DeleteFailedCount = appointmentsToDelete.Count - deletedAppointments.Count;
                for (var index = 0; index < appointmentsToDelete.Count; index++)
                {
                    SourceAppointments.Remove(appointmentsToDelete[index]);
                }
            }
            return isSuccess;
        }
 /// <summary>
 ///     Gets appointments to add in the destination calendar
 /// </summary>
 /// <param name="syncProfile"></param>
 /// <param name="sourceList"></param>
 /// <param name="destinationList"></param>
 /// <param name="appointmentsToAdd"></param>
 /// <returns>
 /// </returns>
 private void EvaluateAppointmentsToAdd(CalendarSyncProfile syncProfile, List<Appointment> sourceList,
     List<Appointment> destinationList, List<Appointment> appointmentsToAdd)
 {
     if (!destinationList.Any())
     {
         appointmentsToAdd.AddRange(sourceList);
         //All entries need to be added
         return;
     }
     if (syncProfile.SyncSettings.SyncMode == SyncModeEnum.TwoWay &&
         syncProfile.SyncSettings.KeepLastModifiedVersion)
     {
         foreach (var sourceAppointment in sourceList)
         {
             //Allow adding appointments which are original entries & do not have a child in this calendar
             if (sourceAppointment.SourceId == null && sourceAppointment.ChildId == null)
             {
                 var destinationAppointment = destinationList.FirstOrDefault(t =>
                    t.Equals(sourceAppointment));
                 if (destinationAppointment == null)
                 {
                     appointmentsToAdd.Add(sourceAppointment);
                 }
             }
         }
     }
     else
     {
         foreach (var sourceAppointment in sourceList)
         {
             if (sourceAppointment.SourceId == null)
             {
                 var destinationAppointment = destinationList.FirstOrDefault(t =>
                     t.Equals(sourceAppointment));
                 if (destinationAppointment == null)
                 {
                     appointmentsToAdd.Add(sourceAppointment);
                 }
             }
         }
     }
 }
        /// <summary>
        ///     Add appointments to source
        /// </summary>
        /// <param name="syncProfile"></param>
        /// <param name="syncMetric"></param>
        /// <param name="sourceCalendarSpecificData"></param>
        /// <returns>
        /// </returns>
        private bool AddSourceAppointments(CalendarSyncProfile syncProfile, SyncMetric syncMetric,
            IDictionary<string, object> sourceCalendarSpecificData)
        {
            //Update status for reading entries to add
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.ReadingEntriesToAdd,
                SourceCalendarService.CalendarServiceName);
            //Get entries to add
            CalendarSyncEngine.GetSourceEntriesToAdd(syncProfile, SourceAppointments, DestinationAppointments);
            var appointmentsToAdd = CalendarSyncEngine.SourceAppointmentsToAdd;
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.EntriesToAdd, appointmentsToAdd.Count);
            if (appointmentsToAdd.Count == 0)
            {
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                return true;
            }
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.AddingEntries, SourceCalendarService.CalendarServiceName);

            //Add entries to calendar
            var addedAppointments = SourceCalendarService.AddCalendarEvents(appointmentsToAdd,
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Description),
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Reminders),
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Attendees),
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.AttendeesToDescription),
                sourceCalendarSpecificData)
                .Result;
            var isSuccess = addedAppointments.IsSuccess;
            //Update status if entries were successfully added
            SyncStatus =
                StatusHelper.GetMessage(isSuccess ? SyncStateEnum.AddEntriesComplete : SyncStateEnum.AddEntriesFailed);
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);

            if (isSuccess)
            {
                syncMetric.SourceMetric.AddCount = appointmentsToAdd.Count;
                LoadSourceId(addedAppointments, DestinationAppointments.CalendarId);
                SourceAppointments.AddRange(addedAppointments);
                if (syncProfile.SyncSettings.SyncMode == SyncModeEnum.TwoWay)
                {
                    var updateDestList = UpdateWithChildId(addedAppointments, DestinationAppointments);
                    CalendarSyncEngine.DestAppointmentsToUpdate.AddRangeCompareForUpdate(updateDestList);
                }
            }

            return isSuccess;
        }
        public bool SyncCalendar(CalendarSyncProfile syncProfile, SyncMetric syncMetric, SyncCallback syncCallback)
        {
            InitiatePreSyncSetup(syncProfile);

            var isSuccess = false;
            if (syncProfile != null)
            {
                CalendarSyncEngine.Clear();
                //Add log for sync mode
                SyncStatus = string.Format("Calendar Sync : {0} {2} {1}", SourceCalendarService.CalendarServiceName,
                    DestinationCalendarService.CalendarServiceName,
                    syncProfile.SyncSettings.SyncMode == SyncModeEnum.TwoWay ? "<===>" : "===>");
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                DateTime startDate, endDate;
                GetDateRange(syncProfile, out startDate, out endDate);
                //Add log for date range
                SyncStatus = string.Format("Date Range : {0} - {1}",
                    startDate.ToString("d"),
                    endDate.ToString("d"));

                //Load calendar specific data
                var sourceCalendarSpecificData =
                    GetCalendarSpecificData(syncProfile.SyncSettings.SourceCalendar, syncProfile);
                var destinationCalendarSpecificData =
                    GetCalendarSpecificData(syncProfile.SyncSettings.DestinationCalendar, syncProfile);

                //Get source and destination appointments
                isSuccess = LoadAppointments(startDate, endDate,
                    sourceCalendarSpecificData,
                    destinationCalendarSpecificData);

                if (isSuccess)
                {
                    syncMetric.SourceMetric.OriginalCount = SourceAppointments.Count;
                    syncMetric.DestMetric.OriginalCount = DestinationAppointments.Count;
                    LoadSourceId(DestinationAppointments, SourceAppointments.CalendarId);
                    LoadSourceId(SourceAppointments, DestinationAppointments.CalendarId);
                }

                if (isSuccess)
                {
                    //Delete destination appointments
                    isSuccess = DeleteDestinationAppointments(syncProfile, syncMetric, destinationCalendarSpecificData, syncCallback);
                }

                if (isSuccess)
                {
                    //Add appointments to destination
                    isSuccess = AddDestinationAppointments(syncProfile, syncMetric, destinationCalendarSpecificData);
                }

                if (isSuccess && syncProfile.SyncSettings.SyncMode == SyncModeEnum.TwoWay)
                {
                    //Delete destination appointments
                    isSuccess = DeleteSourceAppointments(syncProfile, syncMetric, sourceCalendarSpecificData, syncCallback);
                    if (isSuccess)
                    {
                        //If sync mode is two way... add events to source
                        isSuccess = AddSourceAppointments(syncProfile, syncMetric, sourceCalendarSpecificData);
                    }
                }

                if (isSuccess)
                {
                    isSuccess = UpdateEntries(syncProfile, syncMetric, sourceCalendarSpecificData, destinationCalendarSpecificData);
                }
            }
            syncMetric.IsSuccess = isSuccess;
            SourceAppointments = null;
            DestinationAppointments = null;
            SourceCalendarService = null;
            DestinationCalendarService = null;
            return isSuccess;
        }
 /// <summary>
 ///     Gets default calendar profile for the user
 /// </summary>
 /// <returns>
 /// </returns>
 public static CalendarSyncProfile GetDefaultSyncProfile()
 {
     var syncProfile = new CalendarSyncProfile
     {
         SyncSettings = SyncSettings.GetDefault(),
         OutlookSettings =
         {
             OutlookOptions = OutlookOptionsEnum.DefaultProfile |
                              OutlookOptionsEnum.DefaultCalendar
         },
         CalendarEntryOptions =
             CalendarEntryOptionsEnum.Description | CalendarEntryOptionsEnum.Attendees |
             CalendarEntryOptionsEnum.AttendeesToDescription |
             CalendarEntryOptionsEnum.Reminders | CalendarEntryOptionsEnum.AsAppointments
     };
     syncProfile.SetCalendarTypes();
     return syncProfile;
 }
 public bool GetSourceEntriesToAdd(CalendarSyncProfile syncProfile, CalendarAppointments sourceList,
     CalendarAppointments destinationList)
 {
     EvaluateAppointmentsToAdd(syncProfile, destinationList, sourceList, SourceAppointmentsToAdd);
     return true;
 }
        /// <summary>
        /// </summary>
        /// <param name="syncProfile"></param>
        /// <param name="sourceList"></param>
        /// <param name="destinationList"></param>
        /// <param name="destAppointmentsToDelete"></param>
        /// <param name="destAppointmentsToUpdate"></param>
        /// <param name="sourceAppointmentsToUpdate"></param>
        /// <param name="destOrphanEntries"></param>
        /// <returns>
        /// </returns>
        private void EvaluateAppointmentsToDelete(CalendarSyncProfile syncProfile,
            CalendarAppointments sourceList, CalendarAppointments destinationList,
            List<Appointment> destAppointmentsToDelete,
            List<Appointment> destAppointmentsToUpdate, List<Appointment> sourceAppointmentsToUpdate,
            List<Appointment> destOrphanEntries)
        {
            var addDescription =
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Description);
            var addReminders =
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.Reminders);
            var addAttendeesToDescription =
                syncProfile.CalendarEntryOptions.HasFlag(CalendarEntryOptionsEnum.AttendeesToDescription);

            if (!destinationList.Any())
            {
                foreach (var appointment in sourceList)
                {
                    if (appointment.ChildId != null)
                    {
                        var key = AppointmentHelper.GetChildEntryKey(sourceList.CalendarId);
                        if (!appointment.ExtendedProperties.ContainsKey(key))
                        {
                            appointment.ExtendedProperties.Remove(key);
                        }
                        sourceAppointmentsToUpdate.AddCompareForUpdate(appointment);
                    }
                }
                return;
            }

            foreach (var destAppointment in destinationList)
            {
                //If SourceId is null, it is not a copy of any entry from the selected source calendar
                if (destAppointment.SourceId == null)
                {
                    if (syncProfile.SyncSettings.SyncMode == SyncModeEnum.OneWay)
                    {
                        //If mode is one way & user has disabled delete, do not remove this entry, as this is an original entry in the calendar
                        //Else this entry is not a copy of any appointment in source calendar so delete it
                        destOrphanEntries.Add(destAppointment);
                    }
                    else
                    {
                        if (destAppointment.ChildId == null)
                        {
                            var childAppointment = sourceList.FirstOrDefault(t => destAppointment.CompareSourceId(t));
                            if (childAppointment != null)
                            {
                                destAppointment.ChildId = childAppointment.AppointmentId;
                                var key = childAppointment.GetChildEntryKey();
                                if (!destAppointment.ExtendedProperties.ContainsKey(key))
                                {
                                    destAppointment.ExtendedProperties.Add(key, childAppointment.AppointmentId);
                                }
                                else
                                {
                                    destAppointment.ExtendedProperties[key] = childAppointment.AppointmentId;
                                }
                                destAppointmentsToUpdate.AddCompareForUpdate(destAppointment);
                            }
                        }
                        else if (syncProfile.SyncSettings.KeepLastModifiedVersion)
                        {
                            var childAppointment =
                                sourceList.FirstOrDefault(t => t.AppointmentId.Equals(destAppointment.ChildId));
                            if (childAppointment == null)
                            {
                                destAppointmentsToDelete.Add(destAppointment);
                            }
                        }
                    }
                }
                else
                {
                    //If the mode is two way, look for its parent copy in Source calendar
                    Appointment sourceAppointment;
                    if (syncProfile.SyncSettings.SyncMode == SyncModeEnum.TwoWay
                        && syncProfile.SyncSettings.KeepLastModifiedVersion)
                    {
                        //If no entry was found, it is original entry of the calendar, Ignore
                        //If a child entry is found in source calendar, compare
                        sourceAppointment = sourceList.FirstOrDefault(t => t.CompareSourceId(destAppointment));
                        if (sourceAppointment != null)
                        {
                            //If any entry is found in source appointment and its contents are not equal to source appointment,
                            //If an entry is found and i same, ignore
                            if (!CompareAppointments(destAppointment, sourceAppointment, addDescription,
                                addReminders, addAttendeesToDescription))
                            {
                                if (sourceAppointment.LastModified.HasValue && destAppointment.LastModified.HasValue)
                                {
                                    if (destAppointment.LastModified.GetValueOrDefault() >
                                        sourceAppointment.LastModified.GetValueOrDefault())
                                    {
                                        sourceAppointment.CopyDetail(destAppointment,
                                            syncProfile.CalendarEntryOptions);
                                        sourceAppointmentsToUpdate.AddCompareForUpdate(sourceAppointment);
                                        continue;
                                    }
                                }
                                //Destination Calendar Entry is not Matching its Source Calendar Entry, Update it
                                destAppointment.CopyDetail(sourceAppointment, syncProfile.CalendarEntryOptions);
                                destAppointmentsToUpdate.AddCompareForUpdate(destAppointment);
                                continue;
                            }
                        }
                    }

                    //If source appointment is not null, means it is a copy of an existing entry in Source calendar
                    sourceAppointment = sourceList.FirstOrDefault(t => t.CompareSourceId(destAppointment));
                    if (sourceAppointment != null)
                    {
                        //If any entry is found in source appointment and its contents are not equal to source appointment
                        if (!CompareAppointments(destAppointment, sourceAppointment, addDescription, addReminders,
                            addAttendeesToDescription))
                        {
                            destAppointment.CopyDetail(sourceAppointment, syncProfile.CalendarEntryOptions);
                            destAppointmentsToUpdate.AddCompareForUpdate(destAppointment);
                        }
                    }
                    else
                    {
                        //No parent entry is found, delete it
                        sourceAppointment = sourceList.FirstOrDefault(t =>
                            CompareAppointments(destAppointment, t, addDescription, addReminders,
                                addAttendeesToDescription));
                        if (sourceAppointment == null)
                        {
                            //If parent entry isn't found
                            destAppointmentsToDelete.Add(destAppointment);
                        }
                    }
                }
            }
        }
        private void UploadAnalyticsData(CalendarSyncProfile syncProfile, bool isSuccess)
        {
            var syncMetric = new SyncMetric
            {
                IsSuccess = isSuccess,
            };

            AnalyticsService.UploadSyncData(syncMetric, syncProfile.GoogleAccount.Name);
        }
        /// <summary>
        ///     Delete appointments in destination
        /// </summary>
        /// <param name="syncProfile"></param>
        /// <param name="syncMetric"></param>
        /// <param name="destinationCalendarSpecificData"></param>
        /// <param name="syncCallback"></param>
        /// <returns>
        /// </returns>
        private bool DeleteDestinationAppointments(CalendarSyncProfile syncProfile, SyncMetric syncMetric,
            IDictionary<string, object> destinationCalendarSpecificData, SyncCallback syncCallback)
        {
            if (syncProfile.SyncSettings.DisableDelete)
            {
                return true;
            }
            //Updating entry isDeleteOperation status
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.ReadingEntriesToDelete,
                DestinationCalendarService.CalendarServiceName);
            //Getting appointments to isDeleteOperation
            CalendarSyncEngine.GetDestEntriesToDelete(syncProfile,
                SourceAppointments, DestinationAppointments);
            var appointmentsToDelete = CalendarSyncEngine.DestAppointmentsToDelete;

            if (syncProfile.SyncSettings.SyncMode == SyncModeEnum.OneWay)
            {
                if (syncProfile.SyncSettings.ConfirmOnDelete && syncCallback != null)
                {
                    var orphanEntries = Environment.NewLine +
                                        string.Join(Environment.NewLine, CalendarSyncEngine.DestOrphanEntries);
                    //Log Orphan Entries
                    ApplicationLogger.Warn("Orphan entries to delete: " + orphanEntries);

                    var message = string.Format("Are you sure you want to delete {0} orphan entries from {1}?{2}",
                        appointmentsToDelete.Count, DestinationCalendarService.CalendarServiceName,
                        orphanEntries);
                    var e = new SyncEventArgs(message, UserActionEnum.ConfirmDelete);

                    var task = syncCallback(e);
                    if (task.Result)
                    {
                        appointmentsToDelete.AddRange(CalendarSyncEngine.DestOrphanEntries);
                    }
                }
                else if (!syncProfile.SyncSettings.DisableDelete)
                {
                    appointmentsToDelete.AddRange(CalendarSyncEngine.DestOrphanEntries);
                }
            }

            //Updating Get entry isDeleteOperation status
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.EntriesToDelete, appointmentsToDelete.Count);

            if (appointmentsToDelete.Count == 0)
            {
                SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
                return true;
            }

            //Updating isDeleteOperation status
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.DeletingEntries,
                DestinationCalendarService.CalendarServiceName);

            //Deleting entries

            var deletedAppointments = DestinationCalendarService.DeleteCalendarEvents(appointmentsToDelete, destinationCalendarSpecificData)
                    .Result;
            var isSuccess = deletedAppointments.IsSuccess;
            //Update status if entries were successfully deleted
            SyncStatus =
                StatusHelper.GetMessage(isSuccess
                    ? SyncStateEnum.DeletingEntriesComplete
                    : SyncStateEnum.DeletingEntriesFailed);
            SyncStatus = StatusHelper.GetMessage(SyncStateEnum.Line);
            if (isSuccess)
            {
                syncMetric.DestMetric.DeleteCount = appointmentsToDelete.Count;
                syncMetric.DestMetric.DeleteFailedCount = appointmentsToDelete.Count - deletedAppointments.Count;
                for (var index = 0; index < appointmentsToDelete.Count; index++)
                {
                    DestinationAppointments.Remove(appointmentsToDelete[index]);
                }
            }

            return isSuccess;
        }
        public string SyncNow(CalendarSyncProfile syncProfile, SyncMetric syncMetric, SyncCallback syncCallback)
        {
            try
            {
                if (syncProfile.GoogleAccount == null || syncProfile.GoogleAccount.GoogleCalendar == null ||
                    !syncProfile.ValidateOutlookSettings())
                {
                    _messageService.ShowMessageAsync(
                        "Please configure Google and Outlook calendar in settings to continue.");
                    return "Invalid Settings";
                }
                ResetSyncData();

                var isSyncComplete = _calendarUpdateService.SyncCalendar(syncProfile, syncMetric, syncCallback);
                return isSyncComplete ? null : "Error Occurred";
            }
            catch (AggregateException exception)
            {
                var flattenException = exception.Flatten();
                _messageService.ShowMessageAsync(flattenException.Message);
                _applicationLogger.Error(exception);
                return flattenException.Message;
            }
            catch (Exception exception)
            {
                _messageService.ShowMessageAsync(exception.Message);
                _applicationLogger.Error(exception);
                return exception.Message;
            }
        }
 public ProfileViewModel(CalendarSyncProfile syncProfile, IGoogleCalendarService googleCalendarService,
     IOutlookCalendarService outlookCalendarService,
     IMessageService messageService, IExchangeWebCalendarService exchangeWebCalendarService,
     ApplicationLogger applicationLogger, IAccountAuthenticationService accountAuthenticationService)
 {
     SyncProfile = syncProfile;
     ExchangeWebCalendarService = exchangeWebCalendarService;
     ApplicationLogger = applicationLogger.GetLogger(GetType());
     AccountAuthenticationService = accountAuthenticationService;
     GoogleCalendarService = googleCalendarService;
     OutlookCalendarService = outlookCalendarService;
     MessageService = messageService;
 }