public ConflictResolution Resolve(string message, Microsoft.Office.Interop.Outlook.AppointmentItem outlookAppointment, Event googleAppointment, Synchronizer sync, bool keepOutlook, bool keepGoogle)
        {
            string name = string.Empty;

            _form.OutlookItemTextBox.Text = string.Empty;
            _form.GoogleItemTextBox.Text  = string.Empty;
            if (outlookAppointment != null)
            {
                name = outlookAppointment.Subject + " - " + outlookAppointment.Start;
                _form.OutlookItemTextBox.Text += outlookAppointment.Body;
            }

            if (googleAppointment != null)
            {
                name = googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment);
                _form.GoogleItemTextBox.Text += googleAppointment.Description;
            }

            //ToDo: Make it more flexible
            _form.keepGoogle.Enabled  = keepGoogle;
            _form.keepOutlook.Enabled = keepOutlook;
            _form.AllCheckBox.Visible = true;
            _form.messageLabel.Text   = message;

            return(Resolve());
        }
        public DeleteResolution ResolveDelete(Event googleAppointment)
        {
            _form.Text = "Outlook appointment deleted";
            _form.messageLabel.Text =
                "Outlook appointment \"" + googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment) +
                "\" doesn't exist aynmore. Do you want to delete it also on Google side?";

            _form.OutlookItemTextBox.Text = String.Empty;
            _form.GoogleItemTextBox.Text += googleAppointment.Description;


            _form.keepOutlook.Text = "Keep Google";
            _form.keepGoogle.Text  = "Delete Google";
            _form.skip.Enabled     = false;

            return(ResolveDeletedOutlook());
        }
        public static void SyncAppointments(Synchronizer sync)
        {
            for (int i = 0; i < sync.Appointments.Count; i++)
            {
                AppointmentMatch match = sync.Appointments[i];
                if (NotificationReceived != null)
                {
                    string name = string.Empty;
                    if (match.OutlookAppointment != null)
                    {
                        name = match.OutlookAppointment.Subject + " - " + match.OutlookAppointment.Start;
                    }
                    else if (match.GoogleAppointment != null)
                    {
                        name = match.GoogleAppointment.Summary + " - " + Synchronizer.GetTime(match.GoogleAppointment);
                    }
                    NotificationReceived(String.Format("Syncing appointment {0} of {1}: {2} ...", i + 1, sync.Appointments.Count, name));
                }

                SyncAppointment(match, sync);
            }
        }
        public ConflictResolution Resolve(Microsoft.Office.Interop.Outlook.AppointmentItem outlookAppointment, Event googleAppointment, Synchronizer sync, bool isNewMatch)
        {
            string name = string.Empty;

            _form.OutlookItemTextBox.Text = string.Empty;
            _form.GoogleItemTextBox.Text  = string.Empty;
            if (outlookAppointment != null)
            {
                name = outlookAppointment.Subject + " - " + outlookAppointment.Start;
                _form.OutlookItemTextBox.Text += outlookAppointment.Body;
            }

            if (googleAppointment != null)
            {
                name = googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment);
                _form.GoogleItemTextBox.Text += googleAppointment.Description;
            }

            if (isNewMatch)
            {
                _form.messageLabel.Text =
                    "This is the first time these appointments \"" + name +
                    "\" are synced. Choose which you would like to keep.";
                _form.skip.Text = "Keep both";
            }
            else
            {
                _form.messageLabel.Text =
                    "Both the Outlook and Google Appointment \"" + name +
                    "\" have been changed. Choose which you would like to keep.";
            }



            return(Resolve());
        }
        /// <summary>
        /// Matches outlook and Google appointment by a) id b) properties.
        /// </summary>
        /// <param name="sync">Syncronizer instance</param>
        /// <returns>Returns a list of match pairs (outlook appointment + Google appointment) for all appointment. Those that weren't matche will have it's peer set to null</returns>
        public static List <AppointmentMatch> MatchAppointments(Synchronizer sync)
        {
            Logger.Log("Matching Outlook and Google appointments...", EventType.Information);
            var result = new List <AppointmentMatch>();

            var googleAppointmentExceptions = new List <Event>();

            //for each outlook appointment try to get Google appointment id from user properties
            //if no match - try to match by properties
            //if no match - create a new match pair without Google appointment.
            //foreach (Outlook._AppointmentItem olc in outlookAppointments)
            var OutlookAppointmentsWithoutSyncId = new Collection <Outlook.AppointmentItem>();

            #region Match first all outlookAppointments by sync id
            for (int i = 1; i <= sync.OutlookAppointments.Count; i++)
            {
                Outlook.AppointmentItem ola;

                try
                {
                    ola = sync.OutlookAppointments[i] as Outlook.AppointmentItem;

                    //For debugging:
                    //if (ola.Subject == "Flex Pilot - Latest Status") // - 14.07.2014 11:30:00
                    //    throw new Exception("Debugging: Flex Pilot - Latest Status");

                    if (ola == null || string.IsNullOrEmpty(ola.Subject) && ola.Start == AppointmentSync.outlookDateMin)
                    {
                        Logger.Log("Empty Outlook appointment found. Skipping", EventType.Warning);
                        sync.SkippedCount++;
                        sync.SkippedCountNotMatches++;
                        continue;
                    }
                    else if (ola.MeetingStatus == Outlook.OlMeetingStatus.olMeetingCanceled || ola.MeetingStatus == Outlook.OlMeetingStatus.olMeetingReceivedAndCanceled)
                    {
                        Logger.Log("Skipping Outlook appointment found because it is cancelled: " + ola.Subject + " - " + ola.Start, EventType.Debug);
                        //sync.SkippedCount++;
                        //sync.SkippedCountNotMatches++;
                        continue;
                    }
                    else if (Synchronizer.MonthsInPast > 0 &&
                             (ola.IsRecurring && ola.GetRecurrencePattern().PatternEndDate < DateTime.Now.AddMonths(-Synchronizer.MonthsInPast) ||
                              !ola.IsRecurring && ola.End < DateTime.Now.AddMonths(-Synchronizer.MonthsInPast)) ||
                             Synchronizer.MonthsInFuture > 0 &&
                             (ola.IsRecurring && ola.GetRecurrencePattern().PatternStartDate > DateTime.Now.AddMonths(Synchronizer.MonthsInFuture) ||
                              !ola.IsRecurring && ola.Start > DateTime.Now.AddMonths(Synchronizer.MonthsInFuture)))
                    {
                        Logger.Log("Skipping Outlook appointment because it is out of months range to sync:" + ola.Subject + " - " + ola.Start, EventType.Debug);
                        continue;
                    }
                    //else if (ola.Subject != "Business Trip")
                    //{//Only for debugging purposes, please comment if not needed
                    //    Logger.Log("Skipping Outlook appointment because of DEBUGGING:" + ola.Subject + " - " + ola.Start, EventType.Error);
                    //    continue;
                    //}
                }
                catch (Exception ex)
                {
                    //this is needed because some appointments throw exceptions
                    Logger.Log("Accessing Outlook appointment threw and exception. Skipping: " + ex.Message, EventType.Warning);
                    sync.SkippedCount++;
                    sync.SkippedCountNotMatches++;
                    continue;
                }

                //try
                //{

                if (NotificationReceived != null)
                {
                    NotificationReceived(String.Format("Matching appointment {0} of {1} by id: {2} ...", i, sync.OutlookAppointments.Count, ola.Subject));
                }

                // Create our own info object to go into collections/lists, so we can free the Outlook objects and not run out of resources / exceed policy limits.
                //OutlookAppointmentInfo olci = new OutlookAppointmentInfo(ola, sync);

                //try to match this appointment to one of Google appointments
                Outlook.ItemProperties userProperties = ola.ItemProperties;
                Outlook.ItemProperty   idProp         = userProperties[sync.OutlookPropertyNameId];
                try
                {
                    if (idProp != null)
                    {
                        string googleAppointmentId = string.Copy((string)idProp.Value);
                        Event  foundAppointment    = sync.GetGoogleAppointmentById(googleAppointmentId);
                        var    match = new AppointmentMatch(ola, null);



                        if (foundAppointment != null && !foundAppointment.Status.Equals("cancelled"))
                        {
                            //we found a match by google id, that is not deleted or cancelled yet

                            //ToDo: For an unknown reason, some appointments are duplicate in GoogleAppointments, therefore remove all duplicates before continuing
                            while (foundAppointment != null)
                            {
                                match.AddGoogleAppointment(foundAppointment);
                                result.Add(match);
                                //Remove the appointment from the list to not sync it twice
                                if (sync.GoogleAppointments.Contains(foundAppointment))
                                {
                                    sync.GoogleAppointments.Remove(foundAppointment);
                                    foundAppointment = sync.GetGoogleAppointmentById(googleAppointmentId);
                                }
                                else
                                {
                                    foundAppointment = null;
                                }
                            }
                        }
                        else
                        {
                            OutlookAppointmentsWithoutSyncId.Add(ola);
                        }
                    }
                    else
                    {
                        OutlookAppointmentsWithoutSyncId.Add(ola);
                    }
                }
                finally
                {
                    if (idProp != null)
                    {
                        Marshal.ReleaseComObject(idProp);
                    }
                    Marshal.ReleaseComObject(userProperties);
                }
            }
            #endregion
            #region Match the remaining appointments by properties

            for (int i = 0; i < OutlookAppointmentsWithoutSyncId.Count; i++)
            {
                Outlook.AppointmentItem ola = OutlookAppointmentsWithoutSyncId[i];

                if (NotificationReceived != null)
                {
                    NotificationReceived(String.Format("Matching appointment {0} of {1} by unique properties: {2} ...", i + 1, OutlookAppointmentsWithoutSyncId.Count, ola.Subject));
                }

                //no match found by id => match by subject/title
                //create a default match pair with just outlook appointment.
                var match = new AppointmentMatch(ola, null);

                //foreach Google appointment try to match and create a match pair if found some match(es)
                for (int j = sync.GoogleAppointments.Count - 1; j >= 0; j--)
                {
                    var googleAppointment = sync.GoogleAppointments[j];
                    // only match if there is a appointment targetBody, else
                    // a matching Google appointment will be created at each sync
                    if (!googleAppointment.Status.Equals("cancelled") && ola.Subject == googleAppointment.Summary && googleAppointment.Start.DateTime != null && ola.Start == googleAppointment.Start.DateTime)
                    {
                        match.AddGoogleAppointment(googleAppointment);
                        sync.GoogleAppointments.Remove(googleAppointment);

                        //ToDo: For an unknown reason, some appointments are duplicate in GoogleAppointments, therefore remove all duplicates before continuing
                        Event foundAppointment = sync.GetGoogleAppointmentById(AppointmentPropertiesUtils.GetGoogleId(googleAppointment));
                        while (foundAppointment != null)
                        {
                            //we found a match by google id, that is not deleted yet
                            match.AddGoogleAppointment(foundAppointment);
                            //Remove the appointment from the list to not sync it twice
                            if (sync.GoogleAppointments.Contains(foundAppointment))
                            {
                                sync.GoogleAppointments.Remove(foundAppointment);
                                foundAppointment = sync.GetGoogleAppointmentById(AppointmentPropertiesUtils.GetGoogleId(googleAppointment));
                            }
                            else
                            {
                                foundAppointment = null;
                            }
                        }
                    }
                }

                if (match.GoogleAppointment == null)
                {
                    Logger.Log(string.Format("No match found for outlook appointment ({0}) => {1}", match.OutlookAppointment.Subject + " - " + match.OutlookAppointment.Start, (AppointmentPropertiesUtils.GetOutlookGoogleAppointmentId(sync, match.OutlookAppointment) != null ? "Delete from Outlook" : "Add to Google")), EventType.Information);
                }

                result.Add(match);
            }
            #endregion


            //for each Google appointment that's left (they will be nonmatched) create a new match pair without outlook appointment.
            for (int i = 0; i < sync.GoogleAppointments.Count; i++)
            {
                var googleAppointment = sync.GoogleAppointments[i];

                //For debugging:
                //if (googleAppointment.Summary == "Flex Pilot - Latest Status")
                //    throw new Exception("Debugging: Flex Pilot - Latest Status");



                if (NotificationReceived != null)
                {
                    NotificationReceived(String.Format("Adding new Google appointment {0} of {1} by unique properties: {2} ...", i + 1, sync.GoogleAppointments.Count, googleAppointment.Summary));
                }


                if (googleAppointment.RecurringEventId != null)
                {
                    sync.SkippedCountNotMatches++;
                    googleAppointmentExceptions.Add(googleAppointment);
                }
                else if (googleAppointment.Status.Equals("cancelled"))
                {
                    Logger.Log("Skipping Google appointment found because it is cancelled: " + googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment), EventType.Debug);
                    //sync.SkippedCount++;
                    //sync.SkippedCountNotMatches++;
                }
                else if (string.IsNullOrEmpty(googleAppointment.Summary) && (googleAppointment.Start == null || googleAppointment.Start.DateTime == null && googleAppointment.Start.Date == null))
                {
                    // no title or time
                    sync.SkippedCount++;
                    sync.SkippedCountNotMatches++;
                    Logger.Log("Skipped GoogleAppointment because no unique property found (Subject or StartDate):" + googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment), EventType.Warning);
                }
                //else if (googleAppointment.Summary != "Business Trip")
                //{//Only for debugging purposes, please comment if not needed
                //    Logger.Log("Skipping Google appointment because of DEBUGGING:" + googleAppointment.Summary + " - " + googleAppointment.Times[0].StartTime, EventType.Error);
                //    continue;
                //}
                else
                {
                    Logger.Log(string.Format("No match found for Google appointment ({0}) => {1}", googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment), (!string.IsNullOrEmpty(AppointmentPropertiesUtils.GetGoogleOutlookAppointmentId(sync.SyncProfile, googleAppointment)) ? "Delete from Google" : "Add to Outlook")), EventType.Information);
                    var match = new AppointmentMatch(null, googleAppointment);
                    result.Add(match);
                }
            }

            //for each Google appointment exception, assign to proper match
            for (int i = 0; i < googleAppointmentExceptions.Count; i++)
            {
                var googleAppointment = googleAppointmentExceptions[i];
                if (NotificationReceived != null)
                {
                    NotificationReceived(String.Format("Adding Google appointment exception {0} of {1} ...", i + 1, googleAppointmentExceptions.Count, googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment)));
                }

                //Search for original recurrent event in matches
                //AtomId atomId = new AtomId(googleAppointment.Id.AbsoluteUri.Substring(0, googleAppointment.Id.AbsoluteUri.LastIndexOf("/") + 1) + googleAppointment.RecurringEventId);
                bool found = false;
                foreach (AppointmentMatch match in result)
                {
                    if (match.GoogleAppointment != null && googleAppointment.RecurringEventId.Equals(match.GoogleAppointment.Id))
                    {
                        match.GoogleAppointmentExceptions.Add(googleAppointment);
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    Logger.Log(string.Format("No match found for Google appointment exception: {0}", googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment)), EventType.Debug);
                }
            }

            return(result);
        }